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.13k stars 716 forks source link

asyncio prompt example hangs #985

Open r-owen opened 4 years ago

r-owen commented 4 years ago

The following example, taken straight from the documentation (with the first and last line added) hangs for me using Python 3.7.2. I have to kill the process to escape:

import asyncio

from prompt_toolkit import prompt
from prompt_toolkit.eventloop.defaults import use_asyncio_event_loop
from prompt_toolkit.patch_stdout import patch_stdout

# Tell prompt_toolkit to use the asyncio event loop.
use_asyncio_event_loop()

async def my_coroutine():
    while True:
        with patch_stdout():
            result = await prompt('Say something: ', async_=True)
        print('You said: %s' % result)

asyncio.run(my_coroutine())

Can anyone suggest a version that works? I am hoping to make a really simple command-line GUI that uses asyncio and takes input in one panel and prints output in another, but this is a show stopper.

naglis commented 4 years ago

Could reproduce using the provided snippet. Maybe there is some issue with what asyncio.run does, as with a simple run_until_complete seems to work fine:

import asyncio

from prompt_toolkit import prompt
from prompt_toolkit.eventloop.defaults import use_asyncio_event_loop
from prompt_toolkit.patch_stdout import patch_stdout

# Tell prompt_toolkit to use the asyncio event loop.
use_asyncio_event_loop()

async def my_coroutine():
    while True:
        with patch_stdout():
            result = await prompt('Say something: ', async_=True)
        print('You said: %s' % result)

asyncio.get_event_loop().run_until_complete(my_coroutine())

Setup:

jonathanslenders commented 4 years ago

Hi both,

Which operating system and Python version are you using? I just tried (using prompt_toolkit 2.0), and this works fine here.

Also, I'd like to point out that prompt_toolkit 3.0 (master branch) will use asyncio natively. It's not yet released, but it should make the integration much nicer.

edit: prompt_toolkit 3.0 still has some issues with patch_stdout. This PR will fix that: https://github.com/prompt-toolkit/python-prompt-toolkit/pull/990

naglis commented 4 years ago

Hi @jonathanslenders, sorry, I've updated my previous post with the details.

jonathanslenders commented 4 years ago

This is weird. I just tried with Python 3.7.3 and prompt_toolkit 2.0.10 in Docker on WSL, and there it works fine. I'll see if I have some time to try on a Linux box.

naglis commented 4 years ago

I copied the asyncio.run function into my snippet module (gist), and if I replace this line:

loop = events.new_event_loop()

with

loop = events.get_event_loop()

then it works fine. Alternatively, if I call use_asyncio_event_loop() inside my_coroutine() (gist), it works as well.

Not sure if this is helpful, please let me know if I can provide some more information to help debug the problem.

r-owen commented 4 years ago

I see the problem with Python 3.7.2 (from Anaconda) on both CentOS Linux release 7.6.1810 (Core) (running in Docker, but surely that's not relevant?) and macOS 10.14.6.

I can confirm that using

asyncio.get_event_loop().run_until_complete(my_coroutine())

instead of

asyncio.run(my_coroutine())

does work. Thank you for the workaround.

prompt_toolkit 3.0 sounds really promising.