Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

Asynchronously gathering user input seems to break in uvloop but not in default asyncio loop

Offen
#543 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
35/100
Issue-Typ
Bug
Klarheit
Größtenteils klar
Aktivitätsstatus
Veraltet
Tech-Stack
python
Bereich
cli

Rechercherichtung

Beginne mit dem minimalen Reproducer, insbesondere mit connect_stdin_stdout(), asyncio.run(), uvloop.install() und dem aioconsole-Pfad. Führe die sechs aufgeführten Tests unter den angegebenen Python-, uvloop- und Ubuntu-Versionen aus und vergleiche uvloop mit der standardmäßigen asyncio-Schleife. Als erledigt gilt die Aufgabe, wenn die Terminaleingabe asynchron funktioniert und der benutzerdefinierte Ausnahmebericht sich konsistent verhält, ohne hängen zu bleiben oder den Fehler zu verschlucken.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

  • uvloop version: 0.17.0, 0.16.0, 0.15.2
  • Python version: 3.9, 3.11
  • Platform: Lenovo T15g Gen 1, Ubuntu 20.04, Kernel 5.15.0-46-generic
  • Can you reproduce the bug with PYTHONASYNCIODEBUG in env?: Yes, though doesn't look like it provides any useful info
  • Does uvloop behave differently from vanilla asyncio? How?: Asynchronously gathering user input from the terminal doesn't seem to be possible with any method that I am aware of. When not using uvloop, there are two approaches that work fine.

Here is the minimal reproducible example that I am using to try to understand this bug (note requires installing uvloop and :

import os
os.environ['PYTHONASYNCIODEBUG'] = '1'

import asyncio
from typing import Tuple, Type, Optional
from types import TracebackType
import traceback
import sys

import uvloop
import aioconsole


async def connect_stdin_stdout() -> Tuple[asyncio.StreamReader, asyncio.StreamWriter]:
    """Returns asyncio-compatible stream readers and writers for stdin and stdout.
    Useful for CLI interaction without blocking the asyncio event loop.
    """
    loop = asyncio.get_event_loop()

    reader = asyncio.StreamReader()
    r_protocol = asyncio.StreamReaderProtocol(reader)
    await loop.connect_read_pipe(lambda: r_protocol, sys.stdin)

    w_transport, w_protocol = await loop.connect_write_pipe(
        asyncio.streams.FlowControlMixin, sys.stdout
    )
    writer = asyncio.StreamWriter(w_transport, w_protocol, reader, loop)

    return reader, writer

def _log_exceptions(
    exc_type: Type[BaseException],
    exc_value: BaseException,
    exc_traceback: Optional[TracebackType]
): 
    traceback_lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
    print("---- CUSTOM ERROR REPORT ----")
    for line in traceback_lines:
        print(line)
    print("-----------------------------")

async def main(trigger_exception = False, use_aioconsole = False) -> None:
    if use_aioconsole:
        stdout = sys.stdout.buffer
        user_input = (await aioconsole.ainput(">> ")).encode()
    else:
        stdin, stdout = await connect_stdin_stdout()
        stdout.write(b">> ")
        user_input = (await stdin.readline())
        

    if trigger_exception:
        raise RuntimeError()

    stdout.write(user_input)

if __name__ == "__main__":
    # Test 1
    # asyncio.run(main())

    # Test 2
    # uvloop.install()
    # asyncio.run(main())

    # Test 3
    # asyncio.run(main(use_aioconsole=True))

    # Test 4
    # uvloop.install()
    # asyncio.run(main(use_aioconsole=True))

    # Test 5
    # sys.excepthook = _log_exceptions
    # asyncio.run(main(trigger_exception=True, use_aioconsole=True))

    # Test 6
    # uvloop.install()
    # sys.excepthook = _log_exceptions
    # asyncio.run(main(trigger_exception=True, use_aioconsole=True))

There are two main things that I would like to be able to do, that I cannot find a solution for:

  • Gather user input from the terminal asynchronously without using another thread
  • Ensure we can still make some pretty error logs when exceptions occur

Both of these tasks work fine with the default asyncio loop, but seem to fail for me with uvloop. The two approaches I know are connect_stdin_stdout from this stackoverflow answer, and to use a third party library aioconsole (which under the hood does a lot of the same things as the stackoverflow answer).

Are you able to replicate on other systems? It is easy to replicate for me on a variety of python and uvloop installations (noted above).

Is there a workaround I could use to gather user input in a uvloop environment?


In case replication is hard, here are the outputs for each test on my system

  • Test 1
>> a
a
  • Test 2 (note it just hangs forever and never returns)
>> a
  • Test 3
>> a
a⏎ 
  • Test 4
>> a
a⏎
  • Test 5 (note the "custom error report" formatting)
>> a
---- CUSTOM ERROR REPORT ----
Traceback (most recent call last):

  File "/home/ethan/mariana/src/python/potomac/node/test_node.py", line 74, in <module>
    asyncio.run(main(trigger_exception=True, use_aioconsole=True))

  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)

  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()

  File "/home/ethan/mariana/src/python/potomac/node/test_node.py", line 53, in main
    raise RuntimeError()

RuntimeError

-----------------------------
  • Test 6 (apologies that this is totally useless, I think something is getting swallowed but I'm not sure why)
>> a
Error in sys.excepthook:

Original exception was:
Vorherrschende Sprache
Cython
Sterne
11.9k
Forks
615
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus MagicStack/uvloop

Alle Issues in MagicStack/uvloop

Ähnliche Issues

Weitere Issues zu CLI

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.