3.4. 异步IO
3.4.1. 协程
子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。
协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。
优势
一般不需要枷锁
协程极高的执行效率
Python对协程的支持是通过generator实现的。
3.4.2. async/await
import asyncio
async def main():
print('Hello ...')
await asyncio.sleep(1)
print('... World!')
asyncio.run(main())
3.4.3. 同步和异步对比
import asyncio
import time
async def count1():
print("One")
await asyncio.sleep(1)
print("Two")
async def work1():
await asyncio.gather(count1(), count1(), count1())
def v1():
import time
s = time.perf_counter()
asyncio.run(work1())
elapsed = time.perf_counter() - s
print(f"{__file__} executed in {elapsed:0.2f} seconds.")
def v2():
s = time.perf_counter()
work2()
elapsed = time.perf_counter() - s
print(f"{__file__} executed in {elapsed:0.2f} seconds.")
def count2():
print("One")
time.sleep(1)
print("Two")
def work2():
for _ in range(3):
count2()
if __name__ == "__main__":
v1()
v2()
3.4.4. aiohttp
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
from aiohttp import web
async def index(request):
await asyncio.sleep(0.5)
return web.Response(body=b'<h1>Index</h1>')
async def hello(request):
await asyncio.sleep(0.5)
text = '<h1>hello, %s!</h1>' % request.match_info['name']
return web.Response(body=text.encode('utf-8'))
async def init(loop):
app = web.Application(loop=loop)
app.router.add_route('GET', '/', index)
app.router.add_route('GET', '/hello/{name}', hello)
srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000)
print('Server started at http://127.0.0.1:8000...')
return srv
loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()