asyncio
在上一篇文章中,借“廖雪峰”大神的文章介绍了下协程,这次来说下asyncio这个模块
asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。
asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。
在3.5以后对于协程的定义Python有了变动
3.5之前是这样定义的
In [1]: import asyncio
In [2]: @asyncio.coroutine
...: def sleep(x):
...: yield asyncio.sleep(3)
...:
这看着是一个函数,但是其实,这个是一个生成器
3.5以后有了语言级别的支持
不使用装饰器,使用async关键字来定义协程
In [3]: async def sleep(x):
...: await asyncio.sleep(x)
...:
协程是必须跑在EventLoop中的
import asyncio
async def hello():
print("Hello world!")
# 异步调用asyncio.sleep(1):
r = await from asyncio.sleep(1)
print("Hello again!")
# 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()
3.5后对协程的一些支持
async with
在之前介绍上下文管理的时候提到过with方法,with方法实现了__enter__和__exit__的魔术方法,在3.5以后,Python对协程也加入了with的支持
import asyncio
import datetime
import time
class AsyncContentManager:
async def __aenter__(self):
print('aenter: {}'.format(datetime.datetime.now()))
async def __aexit__(self, exc_type, exc_val, exc_tb):
print('aexit: {}'.format(datetime.datetime.now()))
async def so():
async with AsyncContentManager():
time.sleep(1)
print('body: {}'.format(datetime.datetime.now()))
loop = asyncio.get_event_loop()
loop.run_until_complete(so())
loop.run_forever()
使用协程实现EchoServer
server端
import asyncio
async def echo_server(r,w):
while True:
message = await r.read(1024)
print(message.strip())
w.write(message)
await w.drain()
w.close()
loop = asyncio.get_event_loop()
server = asyncio.start_server(echo_server, host='127.0.0.1', port=9999, loop=loop)
loop.run_until_complete(server)
loop.run_forever()
client端(直接拿自官方实例)
import asyncio
@asyncio.coroutine
def tcp_echo_client(message, loop):
reader, writer = yield from asyncio.open_connection('127.0.0.1', 8888,
loop=loop)
print('Send: %r' % message)
writer.write(message.encode())
data = yield from reader.read(100)
print('Received: %r' % data.decode())
print('Close the socket')
writer.close()
message = 'Hello World!'
loop = asyncio.get_event_loop()
loop.run_until_complete(tcp_echo_client(message, loop))
loop.close()