asyncio使用
import asyncio
import time
async def add(x=1,y=2):
print("Add {} + {} ... ".format(x,y))
await asyncio.sleep(2)
return x+y
s=time.time()
loop = asyncio.get_event_loop()
loop.run_until_complete(add())
print('cost:', time.time()-s)
运行结果
Add 1 + 2 ...
cost: 2.0028231143951416
- async就是声明一个函数为协程。而await就是代替原来的yield from。
- 协程里面是不能有阻塞操作的,对于sleep这样的阻塞我们需要用关键是await来包装一下,可以理解为执行一个sleep的协程,sleep 2秒
- 协程需要搭配事件循环才能使用,用asyncio库里面的
get_event_loop
来声明一个异步的事件循环 - 然后把我们的add函数注册到loop中去
- 最后我们等待事件完成
run_until_complete
执行多个task
```python import asyncio import time
async def add(x=1,y=2): print(“Add {} + {} … “.format(x,y)) await asyncio.sleep(2) return x+y s=time.time() loop = asyncio.get_event_loop() task = [add(x,y) for x,y in zip(range(1,10),range(11,10))] loop.run_until_complete(asyncio.wait(tasks)) print(‘cost:’, time.time()-s)
运行结果
```python
Add 2 + 12 ...
Add 4 + 14 ...
Add 6 + 16 ...
Add 5 + 15 ...
Add 3 + 13 ...
Add 1 + 11 ...
Add 8 + 18 ...
Add 9 + 19 ...
Add 7 + 17 ...
cost: 2.0028231143951416
如果获取多个并发的task的结果
import asyncio
import time
async def add(x=1,y=2):
print("Add {} + {} ... ".format(x,y))
await asyncio.sleep(2)
return x+y
s=time.time()
loop = asyncio.get_event_loop()
tasks = [loop.create_task(add(1,2)),loop.create_task(add(11,12)),loop.create_task(add(111,112))]
loop.run_until_complete(asyncio.wait(tasks))
for task in tasks:
print(task.result())
print('cost',time.time()-s)
- 如果我们要获取task的结果,一定要创建一个task, 就是把我们的协程绑定要task上,这里直接用事件循环loop里面的create_task就可以搞定。
- 我们假设有3个并发的add任务需要处理,然后调用run_until_complete来等待3个并发任务完成。
调用task.result查看结果,这里的task其实是_asyncio.Task,是封装的一个类。
asyncio的方法
asyncio.get_event_loop()
声明一个异步的事件循环,主线程调用asyncio.get_event_loop()
时会创建事件循环,你需要把异步的任务丢给这个循环的run_until_complete()
方法asyncio.wait()
声明一个任务列表asyncio.sleep()
一个sleep的协程aiohttp
并发http请求,from aiohttp import ClientSession,首先要建立一个session对象,然后用session对象去打开网页。session可以进行多项操作,比如post
,get
,put
,head
等。
async with ClientSession() as session:
async with session.get(url) as response:
例子
import asyncio
from aiohttp import ClientSession
tasks = []
url = "https://www.baidu.com/{}"
async def hello(url):
async with ClientSession() as session:
async with session.get(url) as response:
response = await response.read()
print(response)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(hello(url))
首先async def 关键字定义了这是个异步函数,await 关键字加在需要等待的操作前面,response.read()
等待request响应,是个耗IO操作。然后使用ClientSession类发起http请求。
多链接异步访问
import time
import asyncio
from aiohttp import ClientSession
tasks = []
url = "https://www.baidu.com/{}"
async def hello(url):
async with ClientSession() as session:
async with session.get(url) as response:
response = await response.read()
# print(response)
print('Hello World:%s' % time.time())
def run():
# 将hello()包装在asyncio的Future对象中,然后将Future对象列表作为任务传递给事件循环
for i in range(5):
task = asyncio.ensure_future(hello(url.format(i)))
tasks.append(task)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
run()
loop.run_until_complete(asyncio.wait(tasks))
ensure_future可将协程封装成Task
收集http响应
可通过asyncio.gather(*tasks)将响应全部收集起来
import time
import asyncio
from aiohttp import ClientSession
tasks = []
url = "https://www.baidu.com/{}"
async def hello(url):
async with ClientSession() as session:
async with session.get(url) as response:
# print(response)
print('Hello World:%s' % time.time())
return await response.read()
def run():
for i in range(5):
task = asyncio.ensure_future(hello(url.format(i)))
tasks.append(task)
result = loop.run_until_complete(asyncio.gather(*tasks))
print(result)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
run()
输出
Hello World:1527765369.0785167
Hello World:1527765369.0845182
Hello World:1527765369.0910277
Hello World:1527765369.0920424
Hello World:1527765369.097017
[b'<!DOCTYPE html>\r\n<!--STATUS OK-->\r\n<html>\r\n<head>\r\n......