1. 使用的库(库 httpx 可通过 pip install httpx 命令安装)

import httpx
import asyncio
import time

2. asyncawait 的普通使用

async def fetch_other(url):
await asyncio.sleep(10)
print(url)


async def test_other():
urls = ['https://httpbin.org/get', 'https://httpbin.org/cookies', 'https://httpbin.org/uuid', 'https://httpbin.org/response-headers?freeform=']
tasks = [asyncio.ensure_future(fetch_other(url)) for url in urls]
await asyncio.gather(*tasks)

3. asyncawait 调用库 httpx

async def fetch_httpx(client, url):
resp = await client.get(url)
return resp.json()


async def test_httpx():
urls = ['https://httpbin.org/get', 'https://httpbin.org/cookies', 'https://httpbin.org/uuid', 'https://httpbin.org/response-headers?freeform=']
async with httpx.AsyncClient() as client:
tasks = [asyncio.ensure_future(fetch_httpx(client, url)) for url in urls]
responses = await asyncio.gather(*tasks)
return responses
def main():
start = time.time()
# 其他流程
loop = asyncio.get_event_loop()
responses = loop.run_until_complete(test_httpx())
for response in responses:
print(response)
loop.run_until_complete(test_other())
loop.close()
# 其他流程
end = time.time()
print('运行时长: %s 秒'%(end-start))

4. 详细情况

4.1 详细代码

import httpx
import asyncio
import time

async def fetch_httpx(client, url):
resp = await client.get(url)
return resp.json()


async def test_httpx():
urls = ['https://httpbin.org/get', 'https://httpbin.org/cookies', 'https://httpbin.org/uuid', 'https://httpbin.org/response-headers?freeform=']
async with httpx.AsyncClient() as client:
tasks = [asyncio.ensure_future(fetch_httpx(client, url)) for url in urls]
responses = await asyncio.gather(*tasks)
return responses

async def fetch_other(url):
await asyncio.sleep(10)
print(url)


async def test_other():
urls = ['https://httpbin.org/get', 'https://httpbin.org/cookies', 'https://httpbin.org/uuid', 'https://httpbin.org/response-headers?freeform=']
tasks = [asyncio.ensure_future(fetch_other(url)) for url in urls]
await asyncio.gather(*tasks)


def main():
start = time.time()
# 其他流程
loop = asyncio.get_event_loop()
responses = loop.run_until_complete(test_httpx())
for response in responses:
print(response)
loop.run_until_complete(test_other())
loop.close()
# 其他流程
end = time.time()
print('运行时长: %s 秒'%(end-start))

if __name__ == '__main__':
main()

4.2 运行输出结果

{'args': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, br', 'Host': 'httpbin.org', 'User-Agent': 'python-httpx/0.23.0', 'X-Amzn-Trace-Id': 'Root=1-641168d8-29511e7271300606309ff8b9'}, 'origin': '106.120.122.135', 'url': 'https://httpbin.org/get'}
{'cookies': {}}
{'uuid': 'fd8c2608-7b3e-47f9-8aec-0c31299771a7'}
{'Content-Length': '87', 'Content-Type': 'application/json', 'freeform': ''}
https://httpbin.org/get
https://httpbin.org/uuid
https://httpbin.org/cookies
https://httpbin.org/response-headers?freeform=
运行时长: 12.626903533935547 秒

5. 其他事项

  文中使用httpx进行异步请求,如果使用aiohttp(通过pip install aiohttp命令安装)进行异步请求时,使用loop.close()关闭事件循环时会抛出异常raise RuntimeError('Event loop is closed')【Python 版本 3.9】。相关代码如下:

import aiohttp
import asyncio

async def fetch_asyncio(session, url):
async with session.get(url) as response:
return await response.json()


async def test_asyncio():
urls = ['https://httpbin.org/get', 'https://httpbin.org/cookies', 'https://httpbin.org/uuid', 'https://httpbin.org/response-headers?freeform=']
async with aiohttp.ClientSession() as session:
tasks = [asyncio.ensure_future(fetch_asyncio(session, url)) for url in urls]
responses = await asyncio.wait(tasks)
return responses

def main():
# 其他流程
loop = asyncio.get_event_loop()
responses = loop.run_until_complete(test_asyncio())
for response in responses:
print(response)
loop.close()
# 其他流程

if __name__ == '__main__':
main()

5.1 运行报错结果

Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x00000118E6D784C0>
Traceback (most recent call last):
File "C:\Program Files\Python39\lib\asyncio\proactor_events.py", line 116, in __del__
self.close()
File "C:\Program Files\Python39\lib\asyncio\proactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "C:\Program Files\Python39\lib\asyncio\base_events.py", line 746, in call_soon
self._check_closed()
File "C:\Program Files\Python39\lib\asyncio\base_events.py", line 510, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed