Löpare

Källkod: Lib/asyncio/runners.py

I detta avsnitt beskrivs asyncioprimitiver på hög nivå för att köra asynciokod.

De är byggda ovanpå en event loop med målet att förenkla asynkron kodanvändning för vanliga, utbredda scenarier.

Kör ett asyncioprogram

asyncio.run(coro, *, debug=None, loop_factory=None)

Kör coro i en asynciohändelseslinga och returnera resultatet.

Argumentet kan vara vilket väntande objekt som helst.

Denna funktion kör awaitable och tar hand om hanteringen av asynciohändelseslingan, finaliserar asynkrona generatorer och stänger exekutorn.

Denna funktion kan inte anropas när en annan asyncio-händelseslinga körs i samma tråd.

Om debug är True kommer händelseslingan att köras i debug-läge. False inaktiverar debug-läget explicit. None används för att respektera de globala inställningarna för Felsökningsläge.

Om loop_factory inte är None används den för att skapa en ny händelseslinga; annars används asyncio.new_event_loop(). Slingan stängs i slutet. Denna funktion bör användas som en huvudingångspunkt för asyncioprogram och bör helst bara anropas en gång. Det rekommenderas att använda loop_factory för att konfigurera händelseslingan i stället för policies. Genom att skicka asyncio.EventLoop kan man köra asyncio utan policysystemet.

Exekveraren får en timeout på 5 minuter för att stängas av. Om exekveraren inte har avslutats inom denna tid utfärdas en varning och exekveraren stängs.

Exempel:

async def main():
    await asyncio.sleep(1)
    skriv ut('hello')

asyncio.run(main())

Tillagd i version 3.7.

Ändrad i version 3.9: Uppdaterad för att använda loop.shutdown_default_executor().

Ändrad i version 3.10: debug är None som standard för att respektera de globala inställningarna för felsökningsläget.

Ändrad i version 3.12: Lagt till parametern loop_factory.

Ändrad i version 3.14: coro kan vara vilket väntande objekt som helst.

Anteckning

Policysystemet asyncio är föråldrat och kommer att tas bort i Python 3.16; från och med då behövs en explicit loop_factory för att konfigurera händelseslingan.

Kontexthanterare för löpare

class asyncio.Runner(*, debug=None, loop_factory=None)

En kontexthanterare som förenklar flera asynkrona funktionsanrop i samma kontext.

Ibland bör flera asynkrona funktioner på toppnivå anropas i samma event loop och contextvars.Context.

Om debug är True kommer händelseslingan att köras i debug-läge. False inaktiverar debug-läget explicit. None används för att respektera de globala inställningarna för Felsökningsläge.

loop_factory kan användas för att åsidosätta skapandet av slingan. Det är loop_factory:s ansvar att ställa in den skapade loopen som den aktuella. Som standard används asyncio.new_event_loop() och ställs in som aktuell händelseslinga med asyncio.set_event_loop() om loop_factory är None.

I grund och botten kan asyncio.run() -exemplet skrivas om med runner-användningen:

async def main():
    await asyncio.sleep(1)
    skriv ut('hello')

med asyncio.Runner() som runner:
    runner.run(main())

Tillagd i version 3.11.

run(coro, *, context=None)

Exekvera coro i den inbäddade händelseslingan.

Argumentet kan vara vilket väntande objekt som helst.

Om argumentet är en coroutine paketeras det in i en Task.

Ett valfritt argument context som endast innehåller nyckelord gör det möjligt att ange en anpassad contextvars.Context för koden som ska köras i. Om context är None används löparens standardkontext.

Returnerar awaitable-resultatet eller skapar ett undantag.

Denna funktion kan inte anropas när en annan asyncio-händelseslinga körs i samma tråd.

Ändrad i version 3.14: coro kan vara vilket väntande objekt som helst.

close()

Stäng löparen.

Slutför asynkrona generatorer, stäng av standardutföraren, stäng händelseslingan och släpp inbäddade contextvars.Context.

get_loop()

Returnerar den händelseslinga som är associerad med runner-instansen.

Anteckning

Runner använder strategin lazy initialization, dess konstruktör initierar inte underliggande strukturer på låg nivå.

Inbäddade loop och context skapas vid with body entry eller vid första anropet av run() eller get_loop().

Hantering av tangentbordsavbrott

Tillagd i version 3.11.

När signal.SIGINT utlöses av Ctrl-C, utlöses KeyboardInterrupt undantag i huvudtråden som standard. Detta fungerar dock inte med asyncio eftersom det kan avbryta asyncio-interna funktioner och kan hindra programmet från att avslutas.

För att mildra detta problem hanterar asyncio signal.SIGINT på följande sätt:

  1. asyncio.Runner.run() installerar en anpassad signal.SIGINT-hanterare innan någon användarkod exekveras och tar bort den när funktionen avslutas.

  2. Runner skapar en huvuduppgift för den passerade coroutinen för dess exekvering.

  3. När signal.SIGINT genereras av Ctrl-C, avbryter den anpassade signalhanteraren huvuduppgiften genom att anropa asyncio.Task.cancel() som genererar asyncio.CancelledError inuti huvuduppgiften. Detta gör att Python-stacken rullas upp, try/except och try/finally block kan användas för resursrensning. Efter att huvuduppgiften har avbrutits ger asyncio.Runner.run() upphov till KeyboardInterrupt.

  4. En användare kan skriva en tät loop som inte kan avbrytas av asyncio.Task.cancel(), i vilket fall den andra följande Ctrl-C omedelbart ger upphov till KeyboardInterrupt utan att avbryta huvuduppgiften.