prompt-toolkit / python-prompt-toolkit

Library for building powerful interactive command line applications in Python
https://python-prompt-toolkit.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
9.37k stars 716 forks source link

How to Parallel functions to change the menu and or the buffer? #725

Open 0vert1m3 opened 6 years ago

0vert1m3 commented 6 years ago

How to Parallel (Run more then 1 function simultaneously parallel to the application) functions to change the menu and or the buffer in a fullscreen app ? And is it possible to change layouts dynamically ?

I have tryed this:

def run():
    t1 = threading.Thread(target=application.run())
    t2 = threading.Thread(target=testprt())
    t1.daemon = True
    t2.daemon = True
    t1.start()
    t2.start()
#    application.run()

if __name__ == '__main__':
    run()

The testprt()

def testprt():
    while True:
        up_r_buffer.text = "1\n"
        time.sleep(1)

FullCode: Here

jonathanslenders commented 6 years ago

Hi @0vert1m3,

Prompt_toolkit has an event loop based architecture. But because we still support Python 2, it implements a custom event loop, very similar to asyncio. If you start doing stuff like this, I recommend using the asyncio event loop.

from prompt_toolkit.eventloop import use_asyncio_event_loop
use_asyncio_event_loop()

You can start threads, but the proper asyncio way of doing that is to run this in an executor. The most important thing to remember is that all manipulations to the UI should happen in the main thread. This can be done using loop.call_soon(): https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_soon

If you don't want to use asyncio. The prompt_toolkit event loops have a method call_from_executor that can be used to schedule any callable in the event loop thread.

jonathanslenders commented 4 years ago

Update on this issue: prompt_toolkit 3.0 now uses asyncio natively.

So, for people stumbling upon this issue: Ideally, the application is written using asyncio itself and all task scheduling happens through the concurrency primitives that asyncio offers. Or, otherwise, synchronous code should run in a separate thread (or asyncio executor), and synchronization has to be done using loop.call_soon_threadsafe.