asyncio (並行計算)

asyncio1Python 3.13.1 Doc.: asyncio: Library for writing concurrent2WIKI: Concurrent Computing code. 

async / await

3.5 版前async def函數內無法使用yieldyield from
會引發SyntaxError錯誤

3.6 版以後有了 Asynchronous Generators 而可以使用yield

使用例

 

import asyncio
import time

async def say_after(delay, what):
  await asyncio.sleep(delay)
  print(what)

async def main():
  print(f"started at {time.strftime('%X')}")

  await say_after(1, 'hello')
  await say_after(2, 'world')

  print(f"finished at {time.strftime('%X')}")

asyncio.run(main())
預期輸出

started at 17:13:52
hello
world
finished at 17:13:55

用 asyncio.create_task() 改寫 main()

await func(...)
⇒ task = asyncio.create_task(func(...)) + await task

 

async def main():
  
  task_1 = asyncio.create_task(
      say_after(1, 'hello')
  )

  task_2 = asyncio.create_task(
      say_after(2, 'world')
  )
  print(f"started at {time.strftime('%X')}")

  await task_1
  await task_2

  print(f"finished at {time.strftime('%X')}")

asyncio.run(main())
用 asyncio.TaskGroup() (since ver. 3.11) 改寫 main()
  1. task = asyncio.create_task(func(...)) 
  2.     await task  await已經包含在 context manager3Python Doc.: With Statement Context Managers4Python Doc.: The with statement

 

async def main():
  
  async with asyncio.TaskGroup() as tg:

    task_1 = tg.create_task(
        say_after(1, 'hello')
    )

    task_2 = tg.create_task(
        say_after(2, 'world')
    )
    print(f"started at {time.strftime('%X')}")

  # The await is implicit when the context manager exits.

  print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

Awaitables

We say that an object is an awaitable object if it can be used in an await expression. Many asyncio APIs are designed to accept awaitables.

There are three main types of awaitable objects: coroutines, Tasks, and Futures.

Coroutines 協程

  • A coroutine function: An async def function.

  • A coroutine object: An object returned by calling a coroutine function.

Tasks

When a coroutine is wrapped into a Task with functions like asyncio.create_task() the coroutine is automatically scheduled to run soon:

 

Task Object
Creating Tasks
Task Cancellation
Task Groups
Terminating a Task Group
Sleeping
Running Tasks Concurrently
Eager Task Factory
Shielding From Cancellation
Timeouts
Waiting Primitives

 

coroutine asyncio.wait(aws, *, timeout=None, return_when=ALL_COMPLETED)
  1. Run Future and Task instances in the aws iterable concurrently and block until the condition specified by return_when.
  2. The aws iterable must not be empty.
  3. Returns two sets of Tasks/Futures: (done, pending).
    ex: done, pending = await asyncio.wait(aws)
  4. timeout (a float or int), if specified, can be used to control the maximum number of seconds to wait before returning.

    Note that this function does not raise TimeoutError. Futures or Tasks that aren’t done when the timeout occurs are simply returned in the second set.

  5. return_when indicates when this function should return.
    It must be one of the following constants:

    1. asyncio.FIRST_COMPLETED
      The function will return when any future finishes or is cancelled.
    2. asyncio.FIRST_EXCEPTION
      The function will return when any future finishes by raising an exception. If no future raises an exception then it is equivalent to ALL_COMPLETED.

    3. asyncio.ALL_COMPLETED
      The function will return when all futures finish or are cancelled

  6. Unlike wait_for(), wait() does not cancel the futures when a timeout occurs.

 

asyncio.as_completed(aws, *, timeout=None)

[async ]for task in as_completed(tasks):
  result = await task
  ...

Running in Threads
Scheduling From Other Threads
Introspection

Futures

Last Updated on 2025/01/01 by A1go

References

目錄
Bitnami