研究下面的代码,Luciano Ramalho 的 Fluent Python 第 18 章是关于 asyncio 模块的优秀资源。另外,永远不要忘记https://docs.python.org/3/library/asyncio.html
上的文档本身
#!/usr/bin/env python3
# spinner_asyncio.py
# credits: Example by Luciano Ramalho inspired by
# Michele Simionato's multiprocessing example in the python-list:
# https://mail.python.org/pipermail/python-list/2009-February/538048.html
import asyncio
import itertools
import sys
@asyncio.coroutine # <1>
def spin(msg):
write, flush = sys.stdout.write, sys.stdout.flush
for char in itertools.cycle('|/-\\'):
status = char + ' ' + msg
write(status)
flush()
write('\x08' * len(status))
try:
yield from asyncio.sleep(.1) # <3>
except asyncio.CancelledError: # <4>
break
write(' ' * len(status) + '\x08' * len(status))
@asyncio.coroutine
def slow_function(): # <5>
# pretend waiting a long time for I/O, Non-blocking call!
yield from asyncio.sleep(3) # <6>
return 42
@asyncio.coroutine
def supervisor(): # <7>
spinner = asyncio.async(spin('thinking!')) # <8>
print('spinner object:', spinner) # <9>
result = yield from slow_function() # <10>
spinner.cancel() # <11>
return result
def main():
loop = asyncio.get_event_loop() # <12>
result = loop.run_until_complete(supervisor()) # <13>
loop.close()
print('Answer:', result)
if __name__ == '__main__':
main()
1: 用于 asyncio 的协程应该用 @asyn 修饰
cio.coroutine。这不是强制性的,但强烈建议这样做。
3:使用 asyncio.sleep(.1) 中的 yield 而不是 time.sleep(.1) 来休眠
不阻塞事件循环。
4:如果在 spin 唤醒后引发 asyncio.CancelledError,那是因为
已请求取消,因此退出循环。
5:slow_function 是协程,使用yield from 让事件循环
在这个协程假装通过睡眠进行 I/O 时继续进行。
6: yield from asyncio.sleep(3) 表达式处理控制流到
主循环,它将在睡眠延迟后恢复这个协程。
7: supervisor也是一个协程,所以它可以通过yield驱动slow_function
来自。
8: asyncio.async(...) 调度自旋协程运行,将其包装在一个任务中
对象,立即返回
9:显示任务对象。输出看起来像 Task pending coro= spin()
在 spinner_asyncio.py:12 运行。
10: 驱动 slow_function()。完成后,获取返回值。
同时,事件循环将继续运行,因为 slow_function
最终使用来自 asyncio.sleep(3) 的 yield 将控制权交还给 main
循环。
11:可以取消一个Task对象;这会在产量处引发 asyncio.CancelledError
协程当前暂停的行。协程可能会捕获
异常和延迟甚至拒绝取消。
12:获取事件循环的引用。
13:驱动supervisor协程完成;协程的返回值
是这个调用的返回值。