Skip to content

Commit a2a4902

Browse files
authored
Merge pull request #3 from laixintao/ch4.3
翻译 ch4.3
2 parents 7074871 + 6cb8063 commit a2a4902

File tree

4 files changed

+150
-10
lines changed

4 files changed

+150
-10
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,143 @@
11
使用Asyncio管理事件循环
22
=======================
3+
4+
Python的Asyncio模块提供了管理事件、协程、任务和线程的方法,以及编写并发代码的原语。此模块的主要组件和概念包括:
5+
6+
- **事件循环**: 在Asyncio模块中,每一个进程都有一个事件循环。
7+
- **协程**: 这是子程序的泛化概念。协程可以在执行期间暂停,这样就可以等待外部的处理(例如IO)完成之后,从之前暂停的地方恢复执行。
8+
- **Futures**: 定义了 ``Future`` 对象,和 ``concurrent.futures`` 模块一样,表示尚未完成的计算。
9+
- **Tasks**: 这是Asyncio的子类,用于封装和管理丙型模式下的协程。
10+
11+
本节中重点讨论事件,事实上,异步编程的上下文中,事件无比重要。因为事件的本质就是异步。
12+
13+
什么是事件循环
14+
--------------
15+
16+
在计算系统中,可以产生事件的实体叫做事件源,能处理事件的实体叫做事件处理者。此外,还有一些第三方实体叫做事件循环。它的作用是管理所有的事件,在整个程序运行过程中不断循环执行,追踪事件发生的顺序将它们放到队列中,当主线程空闲的时候,调用相应的事件处理者处理事件。最后,我们可以通过下面的伪代码来理解事件循环:::
17+
18+
while (1) {
19+
events = getEvents();
20+
for (e in events)
21+
processEvent(e);
22+
}
23+
24+
所有的时间都在 ``while`` 循环中捕捉,然后经过事件处理者处理。事件处理的部分是系统唯一活跃的部分,当一个事件处理完成,流程继续处理下一个事件。
25+
26+
|ready|
27+
-------
28+
29+
Asyncio提供了一下方法来管理事件循环:
30+
31+
- ``loop = get_event_loop()``: 得到当前上下文的事件循环。
32+
- ``loop.call_later(time_delay, callback, argument)``: 延后 ``time_delay`` 秒再执行 ``callback`` 方法。
33+
- ``loop.call_soon(callback, argument)``: 尽可能快调用 ``callback``, ``call_soon()`` 函数结束,主线程回到事件循环之后就会马上调用 ``callback`` 。
34+
- ``loop.time()``: 以float类型返回当前时间循环的内部时间。
35+
- ``asyncio.set_event_loop()``: 为当前上下文设置事件循环。
36+
- ``asyncio.new_event_loop()``: 根据此策略创建一个新的时间循环并返回。
37+
- ``loop.run_forever()``: 在调用 ``stop()`` 之前将一直运行。
38+
39+
|how|
40+
-----
41+
42+
下面的代码中,我们将展示如何使用Asyncio库提供的时间循环创建异步模式的应用。 ::
43+
44+
import asyncio
45+
import datetime
46+
import time
47+
48+
def function_1(end_time, loop):
49+
print ("function_1 called")
50+
if (loop.time() + 1.0) < end_time:
51+
loop.call_later(1, function_2, end_time, loop)
52+
else:
53+
loop.stop()
54+
55+
def function_2(end_time, loop):
56+
print ("function_2 called ")
57+
if (loop.time() + 1.0) < end_time:
58+
loop.call_later(1, function_3, end_time, loop)
59+
else:
60+
loop.stop()
61+
62+
def function_3(end_time, loop):
63+
print ("function_3 called")
64+
if (loop.time() + 1.0) < end_time:
65+
loop.call_later(1, function_1, end_time, loop)
66+
else:
67+
loop.stop()
68+
69+
def function_4(end_time, loop):
70+
print ("function_5 called")
71+
if (loop.time() + 1.0) < end_time:
72+
loop.call_later(1, function_4, end_time, loop)
73+
else:
74+
loop.stop()
75+
76+
loop = asyncio.get_event_loop()
77+
78+
end_loop = loop.time() + 9.0
79+
loop.call_soon(function_1, end_loop, loop)
80+
# loop.call_soon(function_4, end_loop, loop)
81+
loop.run_forever()
82+
loop.close()
83+
84+
运行结果如下:::
85+
86+
python3 event.py
87+
function_1 called
88+
function_2 called
89+
function_3 called
90+
function_1 called
91+
function_2 called
92+
function_3 called
93+
function_1 called
94+
function_2 called
95+
function_3 called
96+
97+
|work|
98+
------
99+
100+
在这个例子中,我们定义了三个异步的任务,相继执行,入下图所示的顺序。
101+
102+
.. image:: ../images/task-execution.png
103+
104+
首先,我们要得到这个事件循环:::
105+
106+
loop = asyncio.get_event_loop()
107+
108+
然后我们通过 ``call_soon`` 方法调用了 ``function_1()`` 函数。 ::
109+
110+
end_loop = loop.time() + 9.0
111+
loop.call_soon(function_1, end_loop, loop)
112+
113+
让我们来看一下 ``function_1()`` 的定义:::
114+
115+
def function_1(end_time, loop):
116+
print ("function_1 called")
117+
if (loop.time() + 1.0) < end_time:
118+
loop.call_later(1, function_2, end_time, loop)
119+
else:
120+
loop.stop()
121+
122+
这个函数通过以下参数定义了应用的异步行为:
123+
124+
- ``end_time``: 定义了 ``function_1()`` 可以运行的最长时间,并通过 ``call_later`` 方法传入到 ``function_2()`` 中作为参数
125+
- ``loop``: 之前通过 ``get_event_loop()`` 方法得到的事件循环
126+
127+
``function_1()`` 的任务非常简单,只是打印出函数名字。当然,里面也可以写非常复杂的操作。 ::
128+
129+
print ("function_1 called")
130+
131+
任务执行结束之后,它将会比较 ``loop.time()`` +1s和设定的运行时间,如果没有超过,使用 ``call_later`` 在1秒之后执行 ``function_2()`` 。 ::
132+
133+
if (loop.time() + 1.0) < end_time:
134+
loop.call_later(1, function_2, end_time, loop)
135+
else:
136+
loop.stop()
137+
138+
``function_2()`` 和 ``function_3()`` 的作用类似。
139+
140+
如果运行的时间超过了设定,时间循环终止。 ::
141+
142+
loop.run_forever()
143+
loop.close()

chapter5/index

Lines changed: 0 additions & 10 deletions
This file was deleted.

dict.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# 通用字典
2+
3+
为了规范本书中常见的一些单词的意思,这里定义一些常用单词的翻译。
4+
5+
同时,在[conf.py](./conf.py)`rst_apilog` 中定义了一些通用的替换规则。例如,输入 `|how|` 在编译的时候将会替换成 `如何做...`.
6+
7+
Parallel 并行
8+
encapsulate 封装
9+
concurrent 并发

images/task-execution.png

30.9 KB
Loading

0 commit comments

Comments
 (0)