使⽤Python3协程语法asyncawait来实现协程异步http请求
都知道Python的多任务有些尴尬,多进程可以⽤多核,但是消耗⼤,线程吧,⽆能⽤多核,是全局解释器锁来回切,所以通常都⽐较青睐协程了,但是协程是基于⽣成器的,不
使⽤第三⽅库的开发成本学习成本就上去了,⽬前⽤的多的就是Gevent,基于Greenlet,使⽤类似于线程,不过在Python3.5以上版本Python提供了协程语法,可以更⽅便的使
⽤,但是新的语法和⼀般的Python语法⼜有些不同,使⽤新的关键字,async,await
下⾯以⼀个例⼦来实现协程异步操作http请求
1import asyncio
2import traceback
3import aiohttp
4
5
6 Normal = "github/"
7
8 async def get_url(url):
9    client = aiohttp.ClientSession()
10try:
11        resp = (url)
12        await client.close()
13return resp
14except:
15        await client.close()
16return traceback.format_exc()
17
18 async def post_url(url, data:dict=None):
19    async with aiohttp.ClientSession() as client:
20try:
21            async with client.post(url, data=data) as resp:
22return resp
23except:
24return traceback.format_exc()
25
26 async def ask_url(url=Normal):
27print("%s==="%url)
28    response = await get_url(url)
29print("%s===Stop . . ."%url)
30print(response)
31
32
33if__name__ == '__main__':
34    urls = [Normal, "baidu", "zhihu"]
35    loop = _event_loop()
36    tasks = [sure_future(ask_url(x)) for x in urls]
37    loop.run_until_complete(asyncio.wait(tasks))
38    loop.close()
执⾏结果如下:
github/===
baidu===
zhihu===
baidu===Stop . . .
<ClientResponse(baidu) [200 OK]>
<CIMultiDictProxy('Date': 'Sat, 19 Jun 2021 14:39:29 GMT', 'Server': 'Apache', 'Last-Modified': 'Tue, 12 Jan 2010 13:48:00 GMT', 'Etag': '"51-47cf7e6ee8400"', 'Accept-Ranges': 'bytes', 'Content-Length': '81', 'Cache-Control': 'max-age=86400 zhihu===Stop . . .
<ClientResponse(www.zhihu/signin?next=/) [200 OK]>
<CIMultiDictProxy('Server': 'CLOUD ELB 1.0.0', 'Date': 'Sat, 19 Jun 2021 14:39:29 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Vary': 'Accept-Encoding', 'content-security-policy': "default-src * blob:; img-src * data: blob: resource: t.captcha.qq. github/===Stop . . .
Traceback (most recent call last):
File "D:/AppData/Python/ForAsync/main.py", line 12, in get_url
resp = (url)
File "C:\Users\Haiton\AppData\Local\Programs\Python\Python38\lib\site-packages\aiohttp\client.py", line 544, in _request
await resp.start(conn)
File "C:\Users\Haiton\AppData\Local\Programs\Python\Python38\lib\site-packages\aiohttp\client_reqrep.py", line 890, in start
message, payload = await self._ad()  # type: ignore
File "C:\Users\Haiton\AppData\Local\Programs\Python\Python38\lib\site-packages\aiohttp\streams.py", line 604, in read
await self._waiter
aiohttp.client_exceptions.ClientOSError: [WinError 121] 信号灯超时时间已到
可以看到,同⼀个线程中,并么有挨个执⾏,⽽是遇到相应差的和需要IO读写的⾃动切换了,其中GitHub最先遇到,但是最后执⾏结束(还是因为超时报错),所以新语法解决
await和async使用方法协程异步IO是有效的。
上⾯的POST和GET通过不同的⽅式实现,是为了展⽰两种⽅式,因为aiohttp的 ClientSession 是⼀个IO的上下⽂,像⽂件⼀样,需要关闭IO,可以像get_url中⼀样,⼿动
close,也可以像post_url⼀样,通过with来⾃动关闭。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。