在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块。
asyncio在python3.4后被内置在python中,使得python的协程创建变得更加方便。
Python 3.5添加了async和await这两个关键字,分别用来替换asyncio.coroutine
和yield from
。自此,协程成为新的语法,而不再是一种生成器类型了。事件循环与协程的引入,可以极大提高高负载下程序的I/O性能。除此之外还增加了async with
(异步上下文管理)、async for
(异步迭代器)语法。特别说的是,在新发布的Python 3.6里面终于可以用异步生成器了
asyncio
的编程模型就是一个消息循环。我们从asyncio
模块中直接获取一个EventLoop
的引用,然后把需要执行的协程扔到EventLoop
中执行,就实现了异步IO。
1,asyncio基本用法
同步/异步的概念:
同步:是指完成事务的逻辑,先执行第一个事务,如果阻塞了,会一直等待,直到这个事务完成,再执行第二个事务,顺序执行
异步:是和同步相对的,异步是指在处理调用这个事务的之后,不会等待这个事务的处理结果,直接处理第二个事务去了,通过状态、通知、回调来通知调用者处理结果。
代码示例:(同步)
import time
def hello():
time.sleep(1)
def run():
for i in range(5):
hello()
print('Hello World:%s' % time.time()) # 任何伟大的代码都是从Hello World 开始的!
if __name__ == '__main__':
run()
输出:(间隔约是1s)
Hello World:1548574672.5149598
Hello World:1548574673.5190861
Hello World:1548574674.524205
Hello World:1548574675.528661
Hello World:1548574676.532924
改为异步执行,主要包含以下步骤:
- 定义异步函数返回异步任务coroutine对象,异步操作需要在
coroutine
中通过yield from
完成 - 将coroutine对象添加进入事件循环,即把异步的任务丢给这个循环的run_until_complete()。多个
coroutine
可以封装成一组Task然后并发执行 - 主线程创建事件循环,调用asyncio.get_event_loop()
- 关闭事件循环
import time
import asyncio
# 定义异步函数
@asyncio.coroutine
def hello():
'''
yield from语法可以让我们方便地调用另一个generator。由于asyncio.sleep()也是一个coroutine,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。
当asyncio.sleep()返回时,线程就可以从yield from拿到返回值(此处是None),然后接着执行下一行语句。
把asyncio.sleep(1)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的coroutine了,因此可以实现并发执行
'''
r = yield from asyncio.sleep(1)
print('Hello World:%s' % time.time())
def run():
for i in range(5):
loop.run_until_complete(hello()) #将协程对象添加到事件循环,运行直到结束
loop = asyncio.get_event_loop() #主线程调用asyncio.get_event_loop()时会创建事件循环
if __name__ =='__main__':
run(