Concurrency In Python 简明教程

Event-Driven Programming

事件驱动编程集中关注事件。最终,程序的流程取决于事件。到目前为止,我们一直处理顺序或并行执行模型,但是具有事件驱动编程概念的模型被称为异步模型。事件驱动编程取决于始终监听新传入事件的事件循环。事件驱动编程的工作取决于事件。一旦事件循环,事件便会决定执行什么以及按什么顺序执行。以下流程图将帮助你了解它的工作原理 -

Event-driven programming focuses on events. Eventually, the flow of program depends upon events. Until now, we were dealing with either sequential or parallel execution model but the model having the concept of event-driven programming is called asynchronous model. Event-driven programming depends upon an event loop that is always listening for the new incoming events. The working of event-driven programming is dependent upon events. Once an event loops, then events decide what to execute and in what order. Following flowchart will help you understand how this works −

driven

Python Module – Asyncio

Asyncio 模块已添加到 Python 3.4 中,它提供了使用协程编写单线程并发代码的基础结构。以下是 Asyncio 模块使用的不同概念 -

Asyncio module was added in Python 3.4 and it provides infrastructure for writing single-threaded concurrent code using co-routines. Following are the different concepts used by the Asyncio module −

The event loop

事件循环是一种处理计算代码中所有事件的功能。它在整个程序执行期间以某种方式进行,并跟踪事件的传入和执行。Asyncio 模块允许每个进程有一个事件循环。以下是 Asyncio 模块提供的用于管理事件循环的一些方法 -

Event-loop is a functionality to handle all the events in a computational code. It acts round the way during the execution of whole program and keeps track of the incoming and execution of events. The Asyncio module allows a single event loop per process. Followings are some methods provided by Asyncio module to manage an event loop −

  1. loop = get_event_loop() − This method will provide the event loop for the current context.

  2. loop.call_later(time_delay,callback,argument) − This method arranges for the callback that is to be called after the given time_delay seconds.

  3. loop.call_soon(callback,argument) − This method arranges for a callback that is to be called as soon as possible. The callback is called after call_soon() returns and when the control returns to the event loop.

  4. loop.time() − This method is used to return the current time according to the event loop’s internal clock.

  5. asyncio.set_event_loop() − This method will set the event loop for the current context to the loop.

  6. asyncio.new_event_loop() − This method will create and return a new event loop object.

  7. loop.run_forever() − This method will run until stop() method is called.

Example

以下事件循环示例有助于使用 get_event_loop() 方法打印 hello world 。此示例来自 Python 官方文档。

The following example of event loop helps in printing hello world by using the get_event_loop() method. This example is taken from the Python official docs.

import asyncio

def hello_world(loop):
   print('Hello World')
   loop.stop()

loop = asyncio.get_event_loop()

loop.call_soon(hello_world, loop)

loop.run_forever()
loop.close()

Output

Hello World

Futures

这与 concurrent.futures.Future 类兼容,该类表示尚未完成的计算。asyncio.futures.Future 和 concurrent.futures.Future 之间存在以下区别 -

This is compatible with the concurrent.futures.Future class that represents a computation that has not been accomplished. There are following differences between asyncio.futures.Future and concurrent.futures.Future −

  1. result() and exception() methods do not take a timeout argument and raise an exception when the future isn’t done yet.

  2. Callbacks registered with add_done_callback() are always called via the event loop’s call_soon().

  3. asyncio.futures.Future class is not compatible with the wait() and as_completed() functions in the concurrent.futures package.

Example

以下示例将帮助你了解如何使用 asyncio.futures.future 类。

The following is an example that will help you understand how to use asyncio.futures.future class.

import asyncio

async def Myoperation(future):
   await asyncio.sleep(2)
   future.set_result('Future Completed')

loop = asyncio.get_event_loop()
future = asyncio.Future()
asyncio.ensure_future(Myoperation(future))
try:
   loop.run_until_complete(future)
   print(future.result())
finally:
   loop.close()

Output

Future Completed

Coroutines

Asyncio 中的协程概念类似于 threading 模块下的标准线程对象的概念。这是子程序概念的概括。可以在执行期间挂起协程,以便它等待外部处理并在完成外部处理后从停止处返回。以下两种方式有助于我们实现协程 -

The concept of coroutines in Asyncio is similar to the concept of standard Thread object under threading module. This is the generalization of the subroutine concept. A coroutine can be suspended during the execution so that it waits for the external processing and returns from the point at which it had stopped when the external processing was done. The following two ways help us in implementing coroutines −

async def function()

这是在 Asyncio 模块下实施协程的方法。以下是一个 Python 脚本 −

This is a method for implementation of coroutines under Asyncio module. Following is a Python script for the same −

import asyncio

async def Myoperation():
   print("First Coroutine")

loop = asyncio.get_event_loop()
try:
   loop.run_until_complete(Myoperation())

finally:
   loop.close()

Output

First Coroutine

@asyncio.coroutine decorator

实施协程的另一种方法是使用带有 @asyncio.coroutine 装饰器的生成器。以下是一个 Python 脚本 −

Another method for implementation of coroutines is to utilize generators with the @asyncio.coroutine decorator. Following is a Python script for the same −

import asyncio

@asyncio.coroutine
def Myoperation():
   print("First Coroutine")

loop = asyncio.get_event_loop()
try:
   loop.run_until_complete(Myoperation())

finally:
   loop.close()

Output

First Coroutine

Tasks

Asyncio 模块的这个子类负责在事件循环中并行执行协程。以下 Python 脚本是一个并行处理任务的示例。

This subclass of Asyncio module is responsible for execution of coroutines within an event loop in parallel manner. Following Python script is an example of processing some tasks in parallel.

import asyncio
import time
async def Task_ex(n):
   time.sleep(1)
   print("Processing {}".format(n))
async def Generator_task():
   for i in range(10):
      asyncio.ensure_future(Task_ex(i))
   int("Tasks Completed")
   asyncio.sleep(2)

loop = asyncio.get_event_loop()
loop.run_until_complete(Generator_task())
loop.close()

Output

Tasks Completed
Processing 0
Processing 1
Processing 2
Processing 3
Processing 4
Processing 5
Processing 6
Processing 7
Processing 8
Processing 9

Transports

Asyncio 模块为实施各种类型的通信提供传输类。这些类不是线程安全的,并且在建立通信通道后始终与协议实例配对。

Asyncio module provides transport classes for implementing various types of communication. These classes are not thread safe and always paired with a protocol instance after establishment of communication channel.

以下是继承自 BaseTransport 的不同类型的传输 −

Following are distinct types of transports inherited from the BaseTransport −

  1. ReadTransport − This is an interface for read-only transports.

  2. WriteTransport − This is an interface for write-only transports.

  3. DatagramTransport − This is an interface for sending the data.

  4. BaseSubprocessTransport − Similar to BaseTransport class.

以下是 BaseTransport 类的五种不同方法,随后在四种传输类型中瞬态 −

Followings are five distinct methods of BaseTransport class that are subsequently transient across the four transport types −

  1. close() − It closes the transport.

  2. is_closing() − This method will return true if the transport is closing or is already closed.transports.

  3. get_extra_info(name, default = none) − This will give us some extra information about transport.

  4. get_protocol() − This method will return the current protocol.

Protocols

Asyncio 模块提供了您可以对其进行子类化以实现网络协议的基本类。这些类与传输结合使用;该协议分析传入数据并请求写入传出数据,而传输则负责实际的 I/O 和缓冲。以下是三个协议类 −

Asyncio module provides base classes that you can subclass to implement your network protocols. Those classes are used in conjunction with transports; the protocol parses incoming data and asks for the writing of outgoing data, while the transport is responsible for the actual I/O and buffering. Following are three classes of Protocol −

  1. Protocol − This is the base class for implementing streaming protocols for use with TCP and SSL transports.

  2. DatagramProtocol − This is the base class for implementing datagram protocols for use with UDP transports..

  3. SubprocessProtocol − This is the base class for implementing protocols communicating with child processes through a set of unidirectional pipes.