asyncio
asyncio 是 Python3 引入的标准库,直接内置了对异步 IO 的支持,asyncio 的编程模型是一个消息循环,我们从 asyncio 中直接获取一个 EventLoop 的引用,然后把需要执行的协程放到 EventLoop 中执行,就实现了异步 IO。
import asyncio
@asyncio.coroutine
def hello():
print("Hello world!")
# 异步调用asyncio.sleep(1):
r = yield from asyncio.sleep(1)
print("Hello again!")
# 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()
运行结果:
Hello world!
Hello again!
- @asyncio.coroutine 把一个 generator 标记为 coroutine 类型,然后把 coroutine 放到 EventLoop 中执行。
- hello() 会首先打印出 Hello world!,然后 yield from 语法可以让我们方便调用另一个 generator,由于 asyncio.sleep() 也是一个 coroutine ,所以线程不会等待 asyncio.sleep(),而是直接中断并执行下一个消息循环。当 asyncio.sleep() 返回时,线程就可以从 yield from 拿到返回值(此处是 None ),然后接着执行下一行语句。
- 把 asyncio.sleep(1) 看成是一个耗时一秒的 IO 操作,在此期间主线程并为等待,而是去执行 EventLoop 中其他可以执行的 coroutine 了,因此可以实现并发执行。
用 Task 封装两个 coroutine。
import threading
import asyncio
@asyncio.coroutine
def hello():
print('Hello world! (%s)' % threading.currentThread())
yield from asyncio.sleep(1)
print('Hello again! (%s)' % threading.currentThread())
loop = asyncio.new_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
运行结果:
Hello world! (<_MainThread(MainThread, started 140736185906112)>)
Hello world! (<_MainThread(MainThread, started 140736185906112)>)
(暂停约一秒)
Hello again! (<_MainThread(MainThread, started 140736185906112)>)
Hello again! (<_MainThread(MainThread, started 140736185906112)>)
- 由运行结果可以看出两个 coroutine 是由同一个线程并发执行。如果把 asyncio.sleep() 换成真正的 IO 操作,则多个 coroutine 就可以由一个线程并发执行。
async/await
用 asyncio 提供的 @asyncio.coroutine 可以把一个 generator 标记为 coroutine 类型,然后在 coroutine 内部用 yield from 调用另一个 coroutine 实现异步操作。
为了简化操作,增强可读性,Python3.5 引入了 async 和 await 两个关键字,要使用这两个关键字只需要做两步简单的替换:
* 把 @asyncio.coroutine 替换成 async
* 把 yield from 替换成 await
# 上一节的代码
@asyncio.coroutine
def hello():
print("Hello world!")
r = yield from asyncio.sleep(1)
print("Hello again!")
# 新语法重写
async def hello():
print("Hello world!")
r = await asyncio.sleep(1)
print("Hello again!")
aiohttp
asyncio 可以实现单线程并发 IO 操作。如果仅用在客户端,发挥的威力不大。如果把 asyncio 用在服务器端,例如 Web 服务器,由于 HTTP 连接就是 IO 操作,因此可以用单线程+ coroutine 实现多用户的高并发支持。
asyncio 实现了 TCP、UDP、SSL 等协议,aiohttp 则是基于 asyncio 实现的 HTTP 框架。
本文参考: 廖雪峰: www.liaoxuefeng.com/wiki/101695…
每日格言:过去属于死神,未来属于你自己。
请作者坐公交 支付宝