1. 什么是异步编程¶
1. What is Asynchronous Programming
异步编程是一种不会阻塞的编程范式。
相反,请求和函数调用会在将来的某个时间在后台以某种方式抛出和执行。 这使得调用者可以自由地执行其他活动,并在稍后当结果可用或调用者感兴趣时处理抛出的待执行任务。
在深入了解 asyncio 之前,让我们先了解一下异步编程。
Asynchronous programming is a programming paradigm that does not block.
Instead, requests and function calls are issued and executed somehow in the background at some future time. This frees the caller to perform other activities and handle the results of issued calls at a later time when results are available or when the caller is interested.
Let’s get a handle on asynchronous programming before we dive into asyncio.
1.1 异步任务¶
1.1 Asynchronous Tasks
异步意味着不在同一时刻, 与同步或同时相对.
异步(asynchronous): 时间上不同一时刻或同时进行。
编程时,异步(asynchronous) 意味着请求操作,尽管在请求时并未执行。 这是稍后执行的。
异步(Asynchronous): 可以以相对于彼此的任何顺序同时运行的单独执行流是异步的。
— PAGE 265, 并发的艺术, 2009.
例如,我们可以进行异步函数调用。
这将发出进行函数调用的请求,并且不会等待调用完成。 我们可以选择稍后检查函数调用的状态或结果。
- 异步函数调用(Asynchronous Function Call): 请求在某个时间以某种方式调用某个函数,从而允许调用者恢复并执行其他活动。
函数调用将以某种方式在某个时间在后台发生,并且程序可以执行其他任务或响应其他事件。
这是关键。 我们无法控制如何或何时处理请求,只是我们希望在程序执行其他操作时处理它。
发出异步函数调用通常会产生请求的某些句柄,调用者可以使用该句柄检查调用的状态或获取结果。 这通常被称为未来(future)。
- Future: 异步函数调用的句柄,允许检查调用的状态并检索结果。
异步函数调用和 future 的组合通常称为异步任务。 这是因为它比函数调用更复杂,例如允许取消请求等等。
- 异步任务(Asynchronous Task): 用于指异步函数调用和结果 future 的聚合。
Asynchronous means not at the same time, as opposed to synchronous or at the same time.
asynchronous: not simultaneous or concurrent in time
When programming, asynchronous means that the action is requested, although not performed at the time of the request. It is performed later.
Asynchronous: Separate execution streams that can run concurrently in any order relative to each other are asynchronous.
— PAGE 265, THE ART OF CONCURRENCY, 2009.
For example, we can make an asynchronous function call.
This will issue the request to make the function call and will not wait around for the call to complete. We can choose to check on the status or result of the function call later.
- Asynchronous Function Call: Request that a function is called at some time and in some manner, allowing the caller to resume and perform other activities.
The function call will happen somehow and at some time, in the background, and the program can perform other tasks or respond to other events.
This is key. We don’t have control over how or when the request is handled, only that we would like it handled while the program does other things.
Issuing an asynchronous function call often results in some handle on the request that the caller can use to check on the status of the call or get results. This is often called a future.
- Future: A handle on an asynchronous function call allowing the status of the call to be checked and results to be retrieved.
The combination of the asynchronous function call and future together is often referred to as an asynchronous task. This is because it is more elaborate than a function call, such as allowing the request to be canceled and more.
- Asynchronous Task: Used to refer to the aggregate of an asynchronous function call and resulting future.
1.2 异步编程¶
1.2 Asynchronous Programming
发出异步任务和进行异步函数调用称为异步编程。
那么什么是异步编程呢? 这意味着特定的长时间运行的任务可以在与主应用程序分开的后台运行。 系统不会阻塞所有其他应用程序代码等待该长时间运行的任务完成,而是可以自由地执行不依赖于该任务的其他工作。 然后,一旦长时间运行的任务完成,我们就会收到通知,以便我们可以处理结果。
— PAGE 3, PYTHON CONCURRENCY WITH ASYNCIO, 2022.
- 异步编程(Asynchronous Programming): 使用异步技术,例如发出异步任务或函数调用。
异步编程主要用于非阻塞 I/O,例如从与其他进程或其他系统的套接字连接进行读写。
在非阻塞模式下,当我们向套接字写入字节时,我们可以直接触发并忘记写入或读取,并且我们的应用程序可以继续执行其他任务。
— PAGE 18, PYTHON CONCURRENCY WITH ASYNCIO, 2022.
非阻塞 I/O 是一种执行 I/O 的方式,其中请求读取和写入,但异步执行。 调用者无需等待操作完成即可返回。
读取和写入操作以某种方式执行(例如,通过底层操作系统或构建在其上的系统),并且操作和/或数据的状态稍后由调用者检索,一旦可用,或者当调用者准备好时。
- 非阻塞 I/O(Non-blocking I/O): 通过异步请求和响应执行 I/O 操作,而不是等待操作完成。
因此,我们可以看到非阻塞 I/O 与异步编程的关系。 事实上,我们通过异步编程来使用非阻塞I/O,或者说非阻塞I/O是通过异步编程来实现的。
非阻塞 I/O 与异步编程的结合非常常见,因此通常简称为异步 I/O。
- 异步I/O(Asynchronous I/O): 一种简写,指将异步编程与非阻塞 I/O 相结合。
接下来,让我们研究一下 Python 中的异步编程支持。
Issuing asynchronous tasks and making asynchronous function calls is referred to as asynchronous programming.
So what is asynchronous programming? It means that a particular long-running task can be run in the background separate from the main application. Instead of blocking all other application code waiting for that long-running task to be completed, the system is free to do other work that is not dependent on that task. Then, once the long-running task is completed, we’ll be notified that it is done so we can process the result.
— PAGE 3, PYTHON CONCURRENCY WITH ASYNCIO, 2022.
- Asynchronous Programming: The use of asynchronous techniques, such as issuing asynchronous tasks or function calls.
Asynchronous programming is primarily used with non-blocking I/O, such as reading and writing from socket connections with other processes or other systems.
In non-blocking mode, when we write bytes to a socket, we can just fire and forget the write or read, and our application can go on to perform other tasks.
— PAGE 18, PYTHON CONCURRENCY WITH ASYNCIO, 2022.
Non-blocking I/O is a way of performing I/O where reads and writes are requested, although performed asynchronously. The caller does not need to wait for the operation to complete before returning.
The read and write operations are performed somehow (e.g. by the underlying operating system or systems built upon it), and the status of the action and/or data is retrieved by the caller later, once available, or when the caller is ready.
- Non-blocking I/O: Performing I/O operations via asynchronous requests and responses, rather than waiting for operations to complete.
As such, we can see how non-blocking I/O is related to asynchronous programming. In fact, we use non-blocking I/O via asynchronous programming, or non-blocking I/O is implemented via asynchronous programming.
The combination of non-blocking I/O with asynchronous programming is so common that it is commonly referred to by the shorthand of asynchronous I/O.
- Asynchronous I/O: A shorthand that refers to combining asynchronous programming with non-blocking I/O.
Next, let’s consider asynchronous programming support in Python.
1.3 Python 异步编程¶
1.3 Asynchronous Programming in Python
从广义上讲,Python 中的异步编程是指发出请求而不是阻塞等待请求完成。
我们可以通过多种方式在 Python 中实现异步编程,尽管其中一些与 Python 并发性最相关。
第一个明显的例子是 asyncio 模块。 该模块使用 async/await 语法以及带有套接字和子进程的非阻塞 I/O 直接提供异步编程环境。
asyncio 是异步 I/O 的缩写。 它是一个 Python 库,允许我们使用异步编程模型运行代码。 这让我们可以同时处理多个 I/O 操作,同时仍然允许我们的应用程序保持响应能力。
— PAGE 3, PYTHON CONCURRENCY WITH ASYNCIO, 2022.
它是使用在事件循环中运行的协程实现的,事件循环本身在单个线程中运行。
- Asyncio: Python 通过 asyncio 模块提供的异步编程环境。
更广泛地说,Python 提供了可以异步执行任务的线程和进程。
例如,一个线程可以启动第二个线程来执行函数调用并恢复其他活动。 操作系统将在某个时间调度并执行第二个线程,第一个线程可能会也可能不会手动检查任务的状态。
线程是异步的,这意味着它们可能以不同的速度运行,并且任何线程都可能随时停止不可预测的持续时间。
— PAGE 76, THE ART OF MULTIPROCESSOR PROGRAMMING, 2020.
更具体地说,Python 在 ThreadPoolExecutor 和 ProcessPoolExeuctor 类中提供了基于执行器的线程池和进程池。
这些类使用相同的接口,并通过返回 Future 对象的 submit() 方法支持异步任务。
Concurrent.futures 模块为异步执行可调用对象提供了一个高级接口。 异步执行可以使用 ThreadPoolExecutor 通过线程执行,也可以使用 ProcessPoolExecutor 通过单独的进程执行。
multiprocessing 模块还提供使用 Pool 和 ThreadPool 类中的进程和线程的工作线程池,这些类是 ThreadPoolExecutor 和 ProcessPoolExeuctor 类的前置运行器。
这些类的功能是根据异步执行任务来描述的。 它们明确提供用于执行任务的每个方法的同步(阻塞)和异步(非阻塞)版本。
例如,可以通过 apply() 方法同步发出一次性函数调用,或通过 apply_async() 方法异步发出一次性函数调用。
一个进程池对象,它控制可以向其提交作业的工作进程池。 它支持带有超时和回调的异步结果,并具有并行映射实现。
Python 中的异步编程还有其他方面与 Python 并发性的关系不太严格。
例如,Python 进程异步接收或处理信号。 信号本质上是从其他进程发送的异步事件。
这主要由 signal 模块支持。
现在我们了解了异步编程,让我们仔细看看 asyncio。
要使用所有 CPU 运行事件循环,可以下载我的免费书 以了解如何操作。
Broadly, asynchronous programming in Python refers to making requests and not blocking to wait for them to complete.
We can implement asynchronous programming in Python in various ways, although a few are most relevant for Python concurrency.
The first and obvious example is the asyncio module. This module directly offers an asynchronous programming environment using the async/await syntax and non-blocking I/O with sockets and subprocesses.
asyncio is short for asynchronous I/O. It is a Python library that allows us to run code using an asynchronous programming model. This lets us handle multiple I/O operations at once, while still allowing our application to remain responsive.
— PAGE 3, PYTHON CONCURRENCY WITH ASYNCIO, 2022.
It is implemented using coroutines that run in an event loop that itself runs in a single thread.
- Asyncio: An asynchronous programming environment provided in Python via the asyncio module.
More broadly, Python offers threads and processes that can execute tasks asynchronously.
For example, one thread can start a second thread to execute a function call and resume other activities. The operating system will schedule and execute the second thread at some time and the first thread may or may not check on the status of the task, manually.
Threads are asynchronous, meaning that they may run at different speeds, and any thread can halt for an unpredictable duration at any time.
— PAGE 76, THE ART OF MULTIPROCESSOR PROGRAMMING, 2020.
More concretely, Python provides executor-based thread pools and process pools in the ThreadPoolExecutor and ProcessPoolExeuctor classes.
These classes use the same interface and support asynchronous tasks via the submit() method that returns a Future object.
The concurrent.futures module provides a high-level interface for asynchronously executing callables. The asynchronous execution can be performed with threads, using ThreadPoolExecutor, or separate processes, using ProcessPoolExecutor.
The multiprocessing module also provides pools of workers using processes and threads in the Pool and ThreadPool classes, forerunners to the ThreadPoolExecutor and ProcessPoolExeuctor classes.
The capabilities of these classes are described in terms of worker execution tasks asynchronously. They explicitly provide synchronous (blocking) and asynchronous (non-blocking) versions of each method for executing tasks.
For example, one may issue a one-off function call synchronously via the apply() method or asynchronously via the apply_async() method.
A process pool object which controls a pool of worker processes to which jobs can be submitted. It supports asynchronous results with timeouts and callbacks and has a parallel map implementation.
There are other aspects of asynchronous programming in Python that are less strictly related to Python concurrency.
For example, Python processes receive or handle signals asynchronously. Signals are fundamentally asynchronous events sent from other processes.
This is primarily supported by the signal module.
Now that we know about asynchronous programming, let’s take a closer look at asyncio.
Run your loops using all CPUs, download my FREE book to learn how.
创建日期: 2024年9月4日