asyncio之使用协程处理多任务

使用协程处理多任务

协程是语言专门为并发操作设计的一个结构。一个协程函数当被调用时创建了一个协程对象,调用者可以使用协程的send()方法运行协程函数的代码。协程可以使用await关键字暂停当前执行将控制权交给其他协程,当协程被暂停,它的运行状态被保存下来,可以在下一次被唤醒时继续执行。

启动协程

通过asyncio事件循环有几种不同的方式可以启动协程,最简单的方法是使用run_until_complete()函数,直接传入一个协程。(注意:run_until_complete()函数传入的是一个Future对象,如果传入的是一个协程,协程会被ensure_future()函数自动包装成Future对象,返回Future的结果或者抛出异常)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# asyncio_coroutine.py
import asyncio
async def coroutine():
print('in coroutine')
event_loop = asyncio.get_event_loop()
try:
print('starting coroutine')
coro = coroutine()
print('entering event loop')
event_loop.run_until_complete(coro)
finally:
print('closing event loop')
event_loop.close()

第一步是获取一个事件循环对象,可以使用默认的事件循环类型,也可以使用特定的事件循环,在这个例子中使用了默认的事件循环类型。run_until_complete()函数传入协程对象启动了循环,在协程运行结束后停止了事件循环。

1
2
3
4
5
6
$ python3 asyncio_coroutine.py
starting coroutine
entering event loop
in coroutine
closing event loop

协程返回值

协程的返回值需要等待协程运行完成才能接受。

1
2
3
4
5
6
7
8
9
10
11
12
import asyncio
async def coroutine():
print('in coroutine')
return 'result'
event_loop = asyncio.get_event_loop()
try:
return_value = event_loop.run_until_complete(coroutine())
print('it returned: {!r}'.format(return_value))
finally:
event_loop.close()

在这种情况下,run_until_complete()函数会等待协程运行完成并返回协程的运行结果。

1
2
3
4
$ python3 asyncio_coroutine_return.py
in coroutine
it returned: 'result'

协程链

一个协程可以启动其他的协程并等待返回结果,这使得将任务分解为可重用的部分变得更加容易。下面的例子有两个阶段,必须按顺序执行,但是可以与其他操作并行运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import asyncio
async def outer():
print('in outer')
print('waiting for result1')
result1 = await phase1()
print('waiting for result2')
result2 = await phase2(result1)
return (result1, result2)
async def phase1():
print('in phase1')
return 'result1'
async def phase2(arg):
print('in phase2')
return 'result2 derived from {}'.format(arg)
event_loop = asyncio.get_event_loop()
try:
return_value = event_loop.run_until_complete(outer())
print('return value: {!r}'.format(return_value))
finally:
event_loop.close()

await关键字用来将新的协程任务发送到事件循环。

1
2
3
4
5
6
7
8
$ python3 asyncio_coroutine_chain.py
in outer
waiting for result1
in phase1
waiting for result2
in phase2
return value: ('result1', 'result2 derived from result1')

生成器替代协程

协程函数是asyncio框架设计中的一个关键组件,它们提供了一种语言结构,用于停止执行程序的一部分,保留该调用的状态,并在以后的时间重新进入状态,这些都是并发性框架的重要功能。
Python 3.5引入了新的语言特性,使用async def来定义原生的协程,使用await来交出控制权,上面关于asyncio的例子也充分的体现了这些新的特性。早期版本的Python 3可以使用被asyncio.coroutine()装饰的生成器函数和yield from达到同样的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import asyncio
@asyncio.coroutine
def outer():
print('in outer')
print('waiting for result1')
result1 = yield from phase1()
print('waiting for result2')
result2 = yield from phase2(result1)
return (result1, result2)
@asyncio.coroutine
def phase1():
print('in phase1')
return 'result1'
@asyncio.coroutine
def phase2(arg):
print('in phase2')
return 'result2 derived from {}'.format(arg)
event_loop = asyncio.get_event_loop()
try:
return_value = event_loop.run_until_complete(outer())
print('return value: {!r}'.format(return_value))
finally:
event_loop.close()

上面的例子使用生成器函数替代了原生的协程。

1
2
3
4
5
6
7
8
$ python3 asyncio_generator.py
in outer
waiting for result1
in phase1
waiting for result2
in phase2
return value: ('result1', 'result2 derived from result1')

本文翻译自《The Python3 Standard Library By Example》asyncio相关章节

文章目录
  1. 1. 启动协程
  2. 2. 协程返回值
  3. 3. 协程链
  4. 4. 生成器替代协程
|