异步编程()

这是在阅读源码的异步编程时,与必应的对话.

petals
  • async, await和async with
  • Why use asyncio.run() instead of call the asychronous function directly?
  • asyncio.shield() and asyncio.wait()
  • What is asyncio.get_event_loop()
  • What is event loop?
  • What is asyncio.get_event_policy()?

async, await和async with

async, awaitasync with 是Python中用于编写异步代码的关键字。它们的含义如下:

  • async 用于定义一个协程函数,即一个可以在执行过程中暂停和恢复的函数。协程函数可以使用 await 表达式来等待另一个协程或异步操作的结果,而不会阻塞当前线程。例如:
import asyncio

async def say_hello():
  await asyncio.sleep(1) # 等待一秒钟
  print("Hello!")

asyncio.run(say_hello()) # 运行协程函数
  • await 用于在一个协程函数中暂停当前协程的执行,直到等待的对象(通常是另一个协程或异步操作)返回结果或抛出异常。在等待的过程中,当前线程可以切换到其他可运行的协程,从而实现并发。例如:
import asyncio

async def add(x, y):
  await asyncio.sleep(1) # 等待一秒钟
  return x + y

async def main():
  result = await add(1, 2) # 等待add协程的结果
  print(result)

asyncio.run(main()) # 运行主协程函数
  • async with 用于在一个协程函数中使用异步上下文管理器,即一个可以在进入和退出代码块时执行异步操作的对象。它类似于普通的 with 语句,但是可以处理异步资源和异常。例如:
import aiohttp
import asyncio

async def fetch(url):
  async with aiohttp.ClientSession() as session: # 创建一个异步会话对象
    async with session.get(url) as response: # 发送一个异步GET请求
      return await response.text() # 等待响应文本

async def main():
  html = await fetch("https://www.python.org") # 等待fetch协程的结果
  print(html)

asyncio.run(main()) # 运行主协程函数

源: 与必应的对话, 2023/3/19(1) python – Why do we need and ? – Stack Overflow. https://stackoverflow.com/questions/67092070/why-do-we-need-async-for-and-async-with 访问时间 2023/3/19.
(2) Getting Started With Async Features in Python – Real Python. https://realpython.com/python-async-features/ 访问时间 2023/3/19.
(3) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) python – Why do we need and ? – Stack Overflow. https://stackoverflow.com/questions/67092070/why-do-we-need-async-for-and-async-with 访问时间 2023/3/19.
(2) Getting Started With Async Features in Python – Real Python. https://realpython.com/python-async-features/ 访问时间 2023/3/19.
(3) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.

async for
async with

Why use asyncio.run() instead of call the asychronous function directly?

asyncio.run()

这是一个很好的问题。要运行一个协程函数,我们需要有一个事件循环来管理所有的异步任务。事件循环是一个无限循环,它不断地检查和执行可运行的任务或协程。如果我们直接调用协程函数,它只会返回一个协程对象,而不会执行任何代码。

asyncio.run 函数是一种方便的方法,它可以为我们创建一个事件循环,运行我们传入的协程函数,并在协程函数完成后关闭事件循环。这样我们就不需要自己手动创建和管理事件循环了。

你可以把 asyncio.run 函数看作是异步程序的入口点,它负责启动和停止事件循环,并运行我们定义的主协程函数。

源: 与必应的对话, 2023/3/19(1) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(2) Python asyncio.run() function. https://www.asyncio.run/ 访问时间 2023/3/19.
(3) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(4) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.
(5) python – asyncio run or run_until_complete – Stack Overflow. https://stackoverflow.com/questions/55590343/asyncio-run-or-run-until-complete 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(2) Python asyncio.run() function. https://www.asyncio.run/ 访问时间 2023/3/19.
(3) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(4) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.
(5) python – asyncio run or run_until_complete – Stack Overflow. https://stackoverflow.com/questions/55590343/asyncio-run-or-run-until-complete 访问时间 2023/3/19.

asyncio.shield() and asyncio.wait()

asyncio.shield()
asyncio.wait()

asyncio.shield() 函数可以保护一个任务或协程不被取消。它接受一个可等待的对象作为参数,并返回一个 asyncio.Future 对象。这个Future对象可以直接被等待或者传递给另一个任务或协程。

例如:

import asyncio

async def cancel_me():
    print("cancel_me(): before sleep")

    try:
        # Wait for 1 hour
        await asyncio.sleep(3600)
    except asyncio.CancelledError:
        print("cancel_me(): cancel sleep")
        raise
    finally:
        print("cancel_me(): after sleep")

async def main():
    # Create a "cancel_me" Task
    task = asyncio.create_task(cancel_me())

    # Wait for 1 second
    await asyncio.sleep(1)

    # Shield task from cancellation
    shielded_task = asyncio.shield(task)

    # Cancel task
    task.cancel()

    # Wait for the shielded task to complete
    await shielded_task

asyncio.run(main())

这个例子中,我们创建了一个名为 cancel_me 的任务,它会等待一小时。然后我们等待一秒钟,然后用 asyncio.shield() 函数来保护这个任务不被取消。最后我们取消这个任务,并等待被保护的任务完成。

这个例子的输出是:

cancel_me(): before sleep
cancel_me(): after sleep

可以看到,即使我们取消了原始的任务,但是被保护的任务仍然继续执行,并没有抛出 CancelledError 异常。

asyncio.wait() 函数则可以运行一个可迭代的可等待对象,并阻塞直到满足指定的条件。它有以下参数:

  • aws 是一个可迭代的可等待对象,你想要并发地运行。
  • timeout 是一个可选的超时时间,如果超过了这个时间还没有满足条件,则返回。
  • return_when 是一个常量,表示返回的条件。它有以下几种取值:

    ALL_COMPLETED:当所有的可等待对象都完成时返回。
    FIRST_COMPLETED:当第一个可等待对象完成时返回。
    FIRST_EXCEPTION:当第一个可等待对象抛出异常时返回。
    ALL_EXCEPTIONS:当所有的可等待对象都抛出异常时返回。

  • ALL_COMPLETED:当所有的可等待对象都完成时返回。
  • FIRST_COMPLETED:当第一个可等待对象完成时返回。
  • FIRST_EXCEPTION:当第一个可等待对象抛出异常时返回。
  • ALL_EXCEPTIONS:当所有的可等待对象都抛出异常时返回。

例如:

import asyncio

# A coroutine function that prints its input and waits for a random time between 0 and 3 seconds.
async def worker(num):
    print(f"Worker {num} started")
    await asyncio.sleep(random.randint(0,3))
    print(f"Worker {num} finished")

# A coroutine function that creates three workers and waits for them using asyncio.wait().
async def main():
    
     tasks = []
     for i in range(3):
         tasks.append(asyncio.create_task(worker(i)))
     
     done, pending = await asyncio.wait(tasks, timeout=2, return_when=FIRST_COMPLETED)
     
     print(f"{len(done)} tasks are done.")
     print(f"{len(pending)} tasks are pending.")

     for task in pending:
         task.cancel()

# Run the main coroutine function.
asyncio.run(main())

这个例子中,我们创建了三个名为 worker 的协程函数,它们会打印自己的输入并随机地等待一段时间。然后我们用 asyncio.wait() 函数来等待它们,并设置超时时间为2秒,返回条件为第一个完成。最后我们打印出完成和未完成的任务数量,并取消所有未完成

源: 与必应的对话, 2023/3/19(1) Asyncio Shield From Cancellation. https://superfastpython.com/asyncio-shield/ 访问时间 2023/3/19.
(2) Asyncio Shield From Cancellation. https://superfastpython.com/asyncio-shield/ 访问时间 2023/3/19.
(3) Python asyncio.wait(): Running Tasks Concurrently. https://www.pythontutorial.net/python-concurrency/python-asyncio-wait/ 访问时间 2023/3/19.
(4) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(5) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(6) 深入asyncio.shield – 知乎. https://zhuanlan.zhihu.com/p/75193842 访问时间 2023/3/19.
(7) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(8) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(9) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Asyncio Shield From Cancellation. https://superfastpython.com/asyncio-shield/ 访问时间 2023/3/19.
(2) Asyncio Shield From Cancellation. https://superfastpython.com/asyncio-shield/ 访问时间 2023/3/19.
(3) Python asyncio.wait(): Running Tasks Concurrently. https://www.pythontutorial.net/python-concurrency/python-asyncio-wait/ 访问时间 2023/3/19.
(4) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(5) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(6) 深入asyncio.shield – 知乎. https://zhuanlan.zhihu.com/p/75193842 访问时间 2023/3/19.
(7) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(8) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(9) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.

What is asyncio.get_event_loop()

asyncio.get_event_loop()

asyncio.get_event_loop() 这个函数的功能是获取当前的事件循环。事件循环是asyncio的核心组件,它负责管理和执行协程、任务、回调和IO操作。

当这个函数在一个协程或一个回调中被调用时(例如,使用 call_soon 或类似的API来安排),这个函数会总是返回正在运行的事件循环。如果没有设置正在运行的事件循环,这个函数会返回 get_event_loop_policy().get_event_loop() 的结果。

例如:

import asyncio

# A coroutine function that prints "Hello World" and waits for 1 second.
async def hello():
    print("Hello World")
    await asyncio.sleep(1)

# Get the current event loop.
loop = asyncio.get_event_loop()

# Run the coroutine until it is complete.
loop.run_until_complete(hello())

# Close the event loop.
loop.close()

这个例子中,我们定义了一个名为 hello 的协程函数,它会打印 “Hello World” 并等待一秒钟。然后我们用 asyncio.get_event_loop() 函数来获取当前的事件循环,并用 run_until_complete() 方法来运行这个协程直到它完成。最后我们用 close() 方法来关闭事件循环。

这个例子的输出是:

Hello World

源: 与必应的对话, 2023/3/19(1) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(2) Asyncio之事件循环EventLoop的使用 – 知乎. https://zhuanlan.zhihu.com/p/69210021 访问时间 2023/3/19.
(3) 关于使用python协程模块asyncio创建协程添加进get_event_loop后协程。。。_百度文库. https://wenku.baidu.com/view/397854577cd5360cba1aa8114431b90d6d858951.html 访问时间 2023/3/19.
(4) When to use asyncio.get_running_loop() vs asyncio.get_event_loop()?. https://stackoverflow.com/questions/65206110/when-to-use-asyncio-get-running-loop-vs-asyncio-get-event-loop 访问时间 2023/3/19.
(5) Python Examples of asyncio.get_event_loop – ProgramCreek.com. https://www.programcreek.com/python/example/81225/asyncio.get_event_loop 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(2) Asyncio之事件循环EventLoop的使用 – 知乎. https://zhuanlan.zhihu.com/p/69210021 访问时间 2023/3/19.
(3) 关于使用python协程模块asyncio创建协程添加进get_event_loop后协程。。。_百度文库. https://wenku.baidu.com/view/397854577cd5360cba1aa8114431b90d6d858951.html 访问时间 2023/3/19.
(4) When to use asyncio.get_running_loop() vs asyncio.get_event_loop()?. https://stackoverflow.com/questions/65206110/when-to-use-asyncio-get-running-loop-vs-asyncio-get-event-loop 访问时间 2023/3/19.
(5) Python Examples of asyncio.get_event_loop – ProgramCreek.com. https://www.programcreek.com/python/example/81225/asyncio.get_event_loop 访问时间 2023/3/19.

What is event loop?

事件循环是每个asyncio应用程序的核心。事件循环运行异步任务和回调,执行网络IO操作,和运行子进程。应用程序开发者通常应该使用高级的asyncio函数,例如 asyncio.run(),并且很少需要引用循环对象或调用它的方法。

事件循环的工作原理是这样的:

  • 事件循环会维护一个任务队列,其中存放了需要执行的协程或回调。
  • 事件循环会不断地从任务队列中取出一个任务,并执行它,直到它完成或被暂停。
  • 如果一个任务被暂停(例如,因为遇到了 await 表达式),事件循环会将它放回任务队列,并继续执行下一个任务。
  • 如果一个任务完成了(例如,因为遇到了 return 语句),事件循环会将它从任务队列中移除,并执行下一个任务。
  • 如果所有的任务都完成了或被暂停了,事件循环会等待新的任务加入到队列中。

这样,事件循环可以实现在单线程中并发地运行多个任务。

源: 与必应的对话, 2023/3/19(1) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(2) Python Event Loop. https://www.pythontutorial.net/python-concurrency/python-event-loop/ 访问时间 2023/3/19.
(3) Python Event Loop | Complete Guide to Python Event Loop | Examples – EDUCBA. https://www.educba.com/python-event-loop/ 访问时间 2023/3/19.
(4) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(5) Event Loop — Python 3.7.16 documentation. https://docs.python.org/3.7/library/asyncio-eventloop.html 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(2) Python Event Loop. https://www.pythontutorial.net/python-concurrency/python-event-loop/ 访问时间 2023/3/19.
(3) Python Event Loop | Complete Guide to Python Event Loop | Examples – EDUCBA. https://www.educba.com/python-event-loop/ 访问时间 2023/3/19.
(4) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(5) Event Loop — Python 3.7.16 documentation. https://docs.python.org/3.7/library/asyncio-eventloop.html 访问时间 2023/3/19.

What is asyncio.get_event_policy()?

asyncio.get_event_policy()

get_event_loop_policy() 这个函数的功能是获取当前的事件循环策略。事件循环策略是一个全局对象,用于获取和设置当前的事件循环,以及创建新的事件循环。默认的策略可以被替换为内置的替代方案,以使用不同的事件循环实现,或者被自定义的策略替换,以覆盖这些行为。

例如:

import asyncio

# Get the current event loop policy.
policy = asyncio.get_event_loop_policy()

# Print the type of the policy object.
print(type(policy))

# Print the type of the default event loop for this policy.
print(type(policy.get_default_loop()))

这个例子中,我们用 asyncio.get_event_loop_policy() 函数来获取当前的事件循环策略,并打印它的类型和它所使用的默认事件循环的类型。

这个例子的输出是:

<class 'asyncio.unix_events._UnixDefaultEventLoopPolicy'>
<class 'asyncio.unix_events._UnixSelectorEventLoop'>

源: 与必应的对话, 2023/3/19(1) Policies — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-policy.html 访问时间 2023/3/19.
(2) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(3) 18.5.2. Event loops — Python 3.6.15 documentation. https://docs.python.org/3.6/library/asyncio-eventloops.html 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Policies — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-policy.html 访问时间 2023/3/19.
(2) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(3) 18.5.2. Event loops — Python 3.6.15 documentation. https://docs.python.org/3.6/library/asyncio-eventloops.html 访问时间 2023/3/19.

————————

这是在阅读源码的异步编程时,与必应的对话.

petals
  • async, await和async with
  • Why use asyncio.run() instead of call the asychronous function directly?
  • asyncio.shield() and asyncio.wait()
  • What is asyncio.get_event_loop()
  • What is event loop?
  • What is asyncio.get_event_policy()?

async, await和async with

async, awaitasync with 是Python中用于编写异步代码的关键字。它们的含义如下:

  • async 用于定义一个协程函数,即一个可以在执行过程中暂停和恢复的函数。协程函数可以使用 await 表达式来等待另一个协程或异步操作的结果,而不会阻塞当前线程。例如:
import asyncio

async def say_hello():
  await asyncio.sleep(1) # 等待一秒钟
  print("Hello!")

asyncio.run(say_hello()) # 运行协程函数
  • await 用于在一个协程函数中暂停当前协程的执行,直到等待的对象(通常是另一个协程或异步操作)返回结果或抛出异常。在等待的过程中,当前线程可以切换到其他可运行的协程,从而实现并发。例如:
import asyncio

async def add(x, y):
  await asyncio.sleep(1) # 等待一秒钟
  return x + y

async def main():
  result = await add(1, 2) # 等待add协程的结果
  print(result)

asyncio.run(main()) # 运行主协程函数
  • async with 用于在一个协程函数中使用异步上下文管理器,即一个可以在进入和退出代码块时执行异步操作的对象。它类似于普通的 with 语句,但是可以处理异步资源和异常。例如:
import aiohttp
import asyncio

async def fetch(url):
  async with aiohttp.ClientSession() as session: # 创建一个异步会话对象
    async with session.get(url) as response: # 发送一个异步GET请求
      return await response.text() # 等待响应文本

async def main():
  html = await fetch("https://www.python.org") # 等待fetch协程的结果
  print(html)

asyncio.run(main()) # 运行主协程函数

源: 与必应的对话, 2023/3/19(1) python – Why do we need and ? – Stack Overflow. https://stackoverflow.com/questions/67092070/why-do-we-need-async-for-and-async-with 访问时间 2023/3/19.
(2) Getting Started With Async Features in Python – Real Python. https://realpython.com/python-async-features/ 访问时间 2023/3/19.
(3) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) python – Why do we need and ? – Stack Overflow. https://stackoverflow.com/questions/67092070/why-do-we-need-async-for-and-async-with 访问时间 2023/3/19.
(2) Getting Started With Async Features in Python – Real Python. https://realpython.com/python-async-features/ 访问时间 2023/3/19.
(3) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.

async for
async with

Why use asyncio.run() instead of call the asychronous function directly?

asyncio.run()

这是一个很好的问题。要运行一个协程函数,我们需要有一个事件循环来管理所有的异步任务。事件循环是一个无限循环,它不断地检查和执行可运行的任务或协程。如果我们直接调用协程函数,它只会返回一个协程对象,而不会执行任何代码。

asyncio.run 函数是一种方便的方法,它可以为我们创建一个事件循环,运行我们传入的协程函数,并在协程函数完成后关闭事件循环。这样我们就不需要自己手动创建和管理事件循环了。

你可以把 asyncio.run 函数看作是异步程序的入口点,它负责启动和停止事件循环,并运行我们定义的主协程函数。

源: 与必应的对话, 2023/3/19(1) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(2) Python asyncio.run() function. https://www.asyncio.run/ 访问时间 2023/3/19.
(3) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(4) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.
(5) python – asyncio run or run_until_complete – Stack Overflow. https://stackoverflow.com/questions/55590343/asyncio-run-or-run-until-complete 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(2) Python asyncio.run() function. https://www.asyncio.run/ 访问时间 2023/3/19.
(3) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(4) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.
(5) python – asyncio run or run_until_complete – Stack Overflow. https://stackoverflow.com/questions/55590343/asyncio-run-or-run-until-complete 访问时间 2023/3/19.

asyncio.shield() and asyncio.wait()

asyncio.shield()
asyncio.wait()

asyncio.shield() 函数可以保护一个任务或协程不被取消。它接受一个可等待的对象作为参数,并返回一个 asyncio.Future 对象。这个Future对象可以直接被等待或者传递给另一个任务或协程。

例如:

import asyncio

async def cancel_me():
    print("cancel_me(): before sleep")

    try:
        # Wait for 1 hour
        await asyncio.sleep(3600)
    except asyncio.CancelledError:
        print("cancel_me(): cancel sleep")
        raise
    finally:
        print("cancel_me(): after sleep")

async def main():
    # Create a "cancel_me" Task
    task = asyncio.create_task(cancel_me())

    # Wait for 1 second
    await asyncio.sleep(1)

    # Shield task from cancellation
    shielded_task = asyncio.shield(task)

    # Cancel task
    task.cancel()

    # Wait for the shielded task to complete
    await shielded_task

asyncio.run(main())

这个例子中,我们创建了一个名为 cancel_me 的任务,它会等待一小时。然后我们等待一秒钟,然后用 asyncio.shield() 函数来保护这个任务不被取消。最后我们取消这个任务,并等待被保护的任务完成。

这个例子的输出是:

cancel_me(): before sleep
cancel_me(): after sleep

可以看到,即使我们取消了原始的任务,但是被保护的任务仍然继续执行,并没有抛出 CancelledError 异常。

asyncio.wait() 函数则可以运行一个可迭代的可等待对象,并阻塞直到满足指定的条件。它有以下参数:

  • aws 是一个可迭代的可等待对象,你想要并发地运行。
  • timeout 是一个可选的超时时间,如果超过了这个时间还没有满足条件,则返回。
  • return_when 是一个常量,表示返回的条件。它有以下几种取值:

    ALL_COMPLETED:当所有的可等待对象都完成时返回。
    FIRST_COMPLETED:当第一个可等待对象完成时返回。
    FIRST_EXCEPTION:当第一个可等待对象抛出异常时返回。
    ALL_EXCEPTIONS:当所有的可等待对象都抛出异常时返回。

  • ALL_COMPLETED:当所有的可等待对象都完成时返回。
  • FIRST_COMPLETED:当第一个可等待对象完成时返回。
  • FIRST_EXCEPTION:当第一个可等待对象抛出异常时返回。
  • ALL_EXCEPTIONS:当所有的可等待对象都抛出异常时返回。

例如:

import asyncio

# A coroutine function that prints its input and waits for a random time between 0 and 3 seconds.
async def worker(num):
    print(f"Worker {num} started")
    await asyncio.sleep(random.randint(0,3))
    print(f"Worker {num} finished")

# A coroutine function that creates three workers and waits for them using asyncio.wait().
async def main():
    
     tasks = []
     for i in range(3):
         tasks.append(asyncio.create_task(worker(i)))
     
     done, pending = await asyncio.wait(tasks, timeout=2, return_when=FIRST_COMPLETED)
     
     print(f"{len(done)} tasks are done.")
     print(f"{len(pending)} tasks are pending.")

     for task in pending:
         task.cancel()

# Run the main coroutine function.
asyncio.run(main())

这个例子中,我们创建了三个名为 worker 的协程函数,它们会打印自己的输入并随机地等待一段时间。然后我们用 asyncio.wait() 函数来等待它们,并设置超时时间为2秒,返回条件为第一个完成。最后我们打印出完成和未完成的任务数量,并取消所有未完成

源: 与必应的对话, 2023/3/19(1) Asyncio Shield From Cancellation. https://superfastpython.com/asyncio-shield/ 访问时间 2023/3/19.
(2) Asyncio Shield From Cancellation. https://superfastpython.com/asyncio-shield/ 访问时间 2023/3/19.
(3) Python asyncio.wait(): Running Tasks Concurrently. https://www.pythontutorial.net/python-concurrency/python-asyncio-wait/ 访问时间 2023/3/19.
(4) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(5) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(6) 深入asyncio.shield – 知乎. https://zhuanlan.zhihu.com/p/75193842 访问时间 2023/3/19.
(7) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(8) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(9) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Asyncio Shield From Cancellation. https://superfastpython.com/asyncio-shield/ 访问时间 2023/3/19.
(2) Asyncio Shield From Cancellation. https://superfastpython.com/asyncio-shield/ 访问时间 2023/3/19.
(3) Python asyncio.wait(): Running Tasks Concurrently. https://www.pythontutorial.net/python-concurrency/python-asyncio-wait/ 访问时间 2023/3/19.
(4) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(5) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(6) 深入asyncio.shield – 知乎. https://zhuanlan.zhihu.com/p/75193842 访问时间 2023/3/19.
(7) Coroutines and Tasks — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-task.html 访问时间 2023/3/19.
(8) asyncio — Asynchronous I/O — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio.html 访问时间 2023/3/19.
(9) Async IO in Python: A Complete Walkthrough – Real Python. https://realpython.com/async-io-python/ 访问时间 2023/3/19.

What is asyncio.get_event_loop()

asyncio.get_event_loop()

asyncio.get_event_loop() 这个函数的功能是获取当前的事件循环。事件循环是asyncio的核心组件,它负责管理和执行协程、任务、回调和IO操作。

当这个函数在一个协程或一个回调中被调用时(例如,使用 call_soon 或类似的API来安排),这个函数会总是返回正在运行的事件循环。如果没有设置正在运行的事件循环,这个函数会返回 get_event_loop_policy().get_event_loop() 的结果。

例如:

import asyncio

# A coroutine function that prints "Hello World" and waits for 1 second.
async def hello():
    print("Hello World")
    await asyncio.sleep(1)

# Get the current event loop.
loop = asyncio.get_event_loop()

# Run the coroutine until it is complete.
loop.run_until_complete(hello())

# Close the event loop.
loop.close()

这个例子中,我们定义了一个名为 hello 的协程函数,它会打印 “Hello World” 并等待一秒钟。然后我们用 asyncio.get_event_loop() 函数来获取当前的事件循环,并用 run_until_complete() 方法来运行这个协程直到它完成。最后我们用 close() 方法来关闭事件循环。

这个例子的输出是:

Hello World

源: 与必应的对话, 2023/3/19(1) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(2) Asyncio之事件循环EventLoop的使用 – 知乎. https://zhuanlan.zhihu.com/p/69210021 访问时间 2023/3/19.
(3) 关于使用python协程模块asyncio创建协程添加进get_event_loop后协程。。。_百度文库. https://wenku.baidu.com/view/397854577cd5360cba1aa8114431b90d6d858951.html 访问时间 2023/3/19.
(4) When to use asyncio.get_running_loop() vs asyncio.get_event_loop()?. https://stackoverflow.com/questions/65206110/when-to-use-asyncio-get-running-loop-vs-asyncio-get-event-loop 访问时间 2023/3/19.
(5) Python Examples of asyncio.get_event_loop – ProgramCreek.com. https://www.programcreek.com/python/example/81225/asyncio.get_event_loop 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(2) Asyncio之事件循环EventLoop的使用 – 知乎. https://zhuanlan.zhihu.com/p/69210021 访问时间 2023/3/19.
(3) 关于使用python协程模块asyncio创建协程添加进get_event_loop后协程。。。_百度文库. https://wenku.baidu.com/view/397854577cd5360cba1aa8114431b90d6d858951.html 访问时间 2023/3/19.
(4) When to use asyncio.get_running_loop() vs asyncio.get_event_loop()?. https://stackoverflow.com/questions/65206110/when-to-use-asyncio-get-running-loop-vs-asyncio-get-event-loop 访问时间 2023/3/19.
(5) Python Examples of asyncio.get_event_loop – ProgramCreek.com. https://www.programcreek.com/python/example/81225/asyncio.get_event_loop 访问时间 2023/3/19.

What is event loop?

事件循环是每个asyncio应用程序的核心。事件循环运行异步任务和回调,执行网络IO操作,和运行子进程。应用程序开发者通常应该使用高级的asyncio函数,例如 asyncio.run(),并且很少需要引用循环对象或调用它的方法。

事件循环的工作原理是这样的:

  • 事件循环会维护一个任务队列,其中存放了需要执行的协程或回调。
  • 事件循环会不断地从任务队列中取出一个任务,并执行它,直到它完成或被暂停。
  • 如果一个任务被暂停(例如,因为遇到了 await 表达式),事件循环会将它放回任务队列,并继续执行下一个任务。
  • 如果一个任务完成了(例如,因为遇到了 return 语句),事件循环会将它从任务队列中移除,并执行下一个任务。
  • 如果所有的任务都完成了或被暂停了,事件循环会等待新的任务加入到队列中。

这样,事件循环可以实现在单线程中并发地运行多个任务。

源: 与必应的对话, 2023/3/19(1) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(2) Python Event Loop. https://www.pythontutorial.net/python-concurrency/python-event-loop/ 访问时间 2023/3/19.
(3) Python Event Loop | Complete Guide to Python Event Loop | Examples – EDUCBA. https://www.educba.com/python-event-loop/ 访问时间 2023/3/19.
(4) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(5) Event Loop — Python 3.7.16 documentation. https://docs.python.org/3.7/library/asyncio-eventloop.html 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(2) Python Event Loop. https://www.pythontutorial.net/python-concurrency/python-event-loop/ 访问时间 2023/3/19.
(3) Python Event Loop | Complete Guide to Python Event Loop | Examples – EDUCBA. https://www.educba.com/python-event-loop/ 访问时间 2023/3/19.
(4) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(5) Event Loop — Python 3.7.16 documentation. https://docs.python.org/3.7/library/asyncio-eventloop.html 访问时间 2023/3/19.

What is asyncio.get_event_policy()?

asyncio.get_event_policy()

get_event_loop_policy() 这个函数的功能是获取当前的事件循环策略。事件循环策略是一个全局对象,用于获取和设置当前的事件循环,以及创建新的事件循环。默认的策略可以被替换为内置的替代方案,以使用不同的事件循环实现,或者被自定义的策略替换,以覆盖这些行为。

例如:

import asyncio

# Get the current event loop policy.
policy = asyncio.get_event_loop_policy()

# Print the type of the policy object.
print(type(policy))

# Print the type of the default event loop for this policy.
print(type(policy.get_default_loop()))

这个例子中,我们用 asyncio.get_event_loop_policy() 函数来获取当前的事件循环策略,并打印它的类型和它所使用的默认事件循环的类型。

这个例子的输出是:

<class 'asyncio.unix_events._UnixDefaultEventLoopPolicy'>
<class 'asyncio.unix_events._UnixSelectorEventLoop'>

源: 与必应的对话, 2023/3/19(1) Policies — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-policy.html 访问时间 2023/3/19.
(2) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(3) 18.5.2. Event loops — Python 3.6.15 documentation. https://docs.python.org/3.6/library/asyncio-eventloops.html 访问时间 2023/3/19.

源: 与必应的对话, 2023/3/19(1) Policies — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-policy.html 访问时间 2023/3/19.
(2) Event Loop — Python 3.11.2 documentation. https://docs.python.org/3/library/asyncio-eventloop.html 访问时间 2023/3/19.
(3) 18.5.2. Event loops — Python 3.6.15 documentation. https://docs.python.org/3.6/library/asyncio-eventloops.html 访问时间 2023/3/19.