6. 事件循环是什么¶
6. What is the Event Loop
异步程序的核心是事件循环。
在本节中,我们将花一些时间来了解异步事件循环。
The heart of asyncio programs is the event loop.
In this section, we will take a moment to look at the asyncio event loop.
6.1 Asyncio 的事件循环是什么¶
6.1 What is the Asyncio Event Loop
事件循环是在单线程中执行协程的环境。
asyncio 是一个使用称为单线程事件循环的并发模型以异步方式执行这些协程的库。
— PAGE 3, PYTHON CONCURRENCY WITH ASYNCIO, 2022.
事件循环是 asyncio 程序的核心。
它可以做很多事情,例如:
- 执行协程。
- 执行回调。
- 执行网络输入/输出。
- 运行子进程。
事件循环是每个异步应用程序的核心。 事件循环运行异步任务和回调、执行网络 IO 操作并运行子进程。
事件循环是一种常见的设计模式,并且由于它们在 JavaScript 中的使用,近年来变得非常流行。
JavaScript 有一个基于事件循环的运行时模型,它负责执行代码、收集和处理事件以及执行排队的子任务。 该模型与 C 和 Java 等其他语言中的模型有很大不同。
事件循环,顾名思义,就是一个循环。 它管理任务(协程)列表,并尝试在循环的每次迭代中按顺序执行每个任务,以及执行其他任务,例如执行回调和处理 I/O。
“asyncio”模块提供了访问事件循环并与之交互的功能。
这对于典型的应用程序开发来说不是必需的。
相反,为框架开发人员提供对事件循环的访问,这些开发人员希望在 asyncio 模块之上构建或为其库启用 asyncio。
应用程序开发人员通常应使用高级 asyncio 函数,例如 asyncio.run(),并且很少需要引用循环对象或调用其方法。
asyncio 模块提供了一个低级 API,用于访问当前事件循环对象,以及一套可用于与事件循环交互的方法。
低级 API 旨在供框架开发人员扩展、补充 asyncio 并将其集成到第三方库中。
我们很少需要与 asyncio 程序中的事件循环进行交互,而是使用高级 API。
尽管如此,我们还是可以简单探讨一下如何获取事件循环。
The event loop is an environment for executing coroutines in a single thread.
asyncio is a library to execute these coroutines in an asynchronous fashion using a concurrency model known as a single-threaded event loop.
— PAGE 3, PYTHON CONCURRENCY WITH ASYNCIO, 2022.
The event loop is the core of an asyncio program.
It does many things, such as:
- Execute coroutines.
- Execute callbacks.
- Perform network input/output.
- Run subprocesses.
The event loop is the core of every asyncio application. Event loops run asynchronous tasks and callbacks, perform network IO operations, and run subprocesses.
Event loops are a common design pattern and became very popular in recent times given their use in JavaScript.
JavaScript has a runtime model based on an event loop, which is responsible for executing the code, collecting and processing events, and executing queued sub-tasks. This model is quite different from models in other languages like C and Java.
The event loop, as its name suggests, is a loop. It manages a list of tasks (coroutines) and attempts to progress each in sequence in each iteration of the loop, as well as perform other tasks like executing callbacks and handling I/O.
The “asyncio” module provides functions for accessing and interacting with the event loop.
This is not required for typical application development.
Instead, access to the event loop is provided for framework developers, those that want to build on top of the asyncio module or enable asyncio for their library.
Application developers should typically use the high-level asyncio functions, such as asyncio.run(), and should rarely need to reference the loop object or call its methods.
The asyncio module provides a low-level API for getting access to the current event loop object, as well as a suite of methods that can be used to interact with the event loop.
The low-level API is intended for framework developers that will extend, complement and integrate asyncio into third-party libraries.
We rarely need to interact with the event loop in asyncio programs, in favor of using the high-level API instead.
Nevertheless, we can briefly explore how to get the event loop.
6.2 事件循环如何获取和启动¶
6.2 How To Start and Get An Event Loop
我们在异步应用程序中创建事件循环的典型方法是通过 asyncio.run() 函数。
该函数总是创建一个新的事件循环并在最后关闭它。 它应该用作 asyncio 程序的主要入口点,并且最好只调用一次。
该函数采用一个协程并将其执行直至完成。
我们通常将其传递给我们的主协程并从那里运行我们的程序。
有一些低级函数用于创建和访问事件循环。
asyncio.new_event_loop() 函数将创建一个新的事件循环并返回对其的访问权限。
创建并返回一个新的事件循环对象。
例如:
...
# 创建并访问新的异步事件循环
loop = asyncio.new_event_loop()
我们可以用一个有效的例子来证明这一点。
在下面的示例中,我们将创建一个新的事件循环,然后报告其详细信息。
# SuperFastPython.com
# 创建事件循环的示例
import asyncio
# 创建并访问新的异步事件循环
loop = asyncio.new_event_loop()
# 报告循环的默认值
print(loop)
运行该示例将创建事件循环,然后报告对象的详细信息。
我们可以看到,在这种情况下,事件循环的类型为 _UnixSelectorEventLoop 并且没有运行,但也没有关闭。
<_UnixSelectorEventLoop running=False closed=False debug=False>
如果 asyncio 事件循环已经在运行,我们可以通过 asyncio.get_running_loop() 函数访问它。
返回当前操作系统线程中正在运行的事件循环。 如果没有正在运行的事件循环,则会引发 RuntimeError。 该函数只能从协程或回调中调用。
例如:
...
# 访问正在运行的事件循环
loop = asyncio.get_running_loop()
还有一个用于获取或启动事件循环的函数,称为 asyncio.get_event_loop(),但已弃用 在 Python 3.10 中,不应使用。
The typical way we create an event loop in asyncio applications is via the asyncio.run() function.
This function always creates a new event loop and closes it at the end. It should be used as a main entry point for asyncio programs, and should ideally only be called once.
The function takes a coroutine and will execute it to completion.
We typically pass it to our main coroutine and run our program from there.
There are low-level functions for creating and accessing the event loop.
The asyncio.new_event_loop() function will create a new event loop and return access to it.
Create and return a new event loop object.
For example:
...
# create and access a new asyncio event loop
loop = asyncio.new_event_loop()
We can demonstrate this with a worked example.
In the example below we will create a new event loop and then report its details.
# SuperFastPython.com
# example of creating an event loop
import asyncio
# create and access a new asyncio event loop
loop = asyncio.new_event_loop()
# report defaults of the loop
print(loop)
Running the example creates the event loop, then reports the details of the object.
We can see that in this case the event loop has the type _UnixSelectorEventLoop and is not running, but is also not closed.
<_UnixSelectorEventLoop running=False closed=False debug=False>
If an asyncio event loop is already running, we can get access to it via the asyncio.get_running_loop() function.
Return the running event loop in the current OS thread. If there is no running event loop a RuntimeError is raised. This function can only be called from a coroutine or a callback.
For example:
...
# access he running event loop
loop = asyncio.get_running_loop()
There is also a function for getting or starting the event loop called asyncio.get_event_loop(), but it was deprecated in Python 3.10 and should not be used.
6.3 事件循环对象是什么¶
6.3 What is an Event Loop Object
事件循环作为 Python 对象实现。
事件循环对象定义了事件循环的实现方式,并提供了与循环交互的通用 API,定义在 AbstractEventLoop 类。
不同平台的事件循环有不同的实现。
例如,基于 Windows 和 Unix 的操作系统将以不同的方式实现事件循环,因为这些平台上实现非阻塞 I/O 的底层方式不同。
SelectorEventLoop 类型事件循环是基于 Unix 的操作系统(如 Linux 和 macOS)上的默认设置。
ProactorEventLoop 类型事件循环是 Windows 上的默认设置。
第三方库可以实现自己的事件循环来优化特定功能。
An event loop is implemented as a Python object.
The event loop object defines how the event loop is implemented and provides a common API for interacting with the loop, defined on the AbstractEventLoop class.
There are different implementations of the event loop for different platforms.
For example, Windows and Unix-based operations systems will implement the event loop in different ways, given the different underlying ways that non-blocking I/O is implemented on these platforms.
The SelectorEventLoop type event loop is the default on Unix-based operating systems like Linux and macOS.
The ProactorEventLoop type event loop is the default on Windows.
Third-party libraries may implement their own event loops to optimize for specific features.
6.4 为什么要访问事件循环¶
6.4 Why Get Access to The Event Loop
为什么我们想要访问 asyncio 程序之外的事件循环?
我们可能希望从正在运行的 asyncio 程序外部访问事件循环的原因有很多。
例如:
- 监控任务的进展情况。
- 发出任务并获取结果。
- 解雇并忘记一次性任务。
异步事件循环可以在程序中用作基于协程的任务的线程池的替代方案。
事件循环也可以嵌入到普通的异步程序中并根据需要进行访问。
现在我们对事件循环有了一些了解,让我们看看异步任务。
Why would we want access to an event loop outside of an asyncio program?
There are many reasons why we may want access to the event loop from outside of a running asyncio program.
For example:
- To monitor the progress of tasks.
- To issue and get results from tasks.
- To fire and forget one-off tasks.
An asyncio event loop can be used in a program as an alternative to a thread pool for coroutine-based tasks.
An event loop may also be embedded within a normal asyncio program and accessed as needed.
Now that we know a little about the event loop, let’s look at asyncio tasks.
创建日期: 2024年9月4日