在python中,可以利用asyncio包异步处理IO等操作,极大的增加吞吐。 asyncio的底层依赖的是一个IOLoop。最简单的用法如下:
import asyncio
loop = asyncio.get_event_loop()
async def test():
print("test is run")
await asyncio.sleep(5)
print("test is run over")
for i in range(5):
loop.create_task(test())
loop.run_forever()
带async的函数是一个协程,可以随时调用create_task来将协程包装为任务。 await关键词顾名思义,就是async wait。它将异步化为同步。在同个协程中,await的上下文有序。也就是说,它会“阻塞”住当前协程(但不需要担心,其它协程还是会在loop下好好的运行),直到await后的协程返回结果。 单实例下一种常见的“错误”写法如下:
import asyncio
loop = asyncio.get_event_loop()
async def test():
print("test is run")
await asyncio.sleep(5)
print("test is run over")
async def run():
for i in range(5):
await test()
loop.create_task(run())
loop.run_forever()
在这个程序中, test is run 会每隔5秒出现一次。单实例下,await将异步化为了同步。具体奥妙,须慢慢体会。
create_task 不会阻塞住协程,如果需要等待任务完成,可以在协程中await task.
import asyncio
loop = asyncio.get_event_loop()
async def test():
print("test is run")
await asyncio.sleep(5)
print("test is run over")
async def run():
tasks = []
for i in range(5):
tasks.append(loop.create_task(test()))
await asyncio.wait(tasks)
# 也可以
# for task in tasks:
# await task
print("over")
loop.create_task(run())
loop.run_forever()
在框架中,我们不需要关心loop。所以在实作中,需要上下文有序,则用await等待。不需要,则直接create_task。
如果知道协程的原理,则很容易写出简单的“协程” 比如传统的生产消费模式:
import time
prev_fib = 1
fib = 1
def producer():
global fib
while 1:
yield fib
def consumer():
global fib
global prev_fib
while 1:
now_fib = yield
print(fib)
fib = now_fib + prev_fib
prev_fib = now_fib
p1 = producer()
p2 = consumer()
next(p2)
while 1:
item = next(p1)
p2.send(item)
time.sleep(0.1)