我在某人的代码中看到他们在一个 aiohttp post 调用中发布了一个请求列表,并期望收到返回的响应列表。我自己尝试过,它有效(如果你好奇我的要求,这些是以太坊的区块,我正在与一个实时节点交谈):
def aiohttp_test():
import aiohttp
import asyncio
async def post_test():
req = list()
for ind, i in enumerate(range(15544190, 15544192)):
req.append({"jsonrpc": "2.0", "id": ind + 1, "method": "eth_getBlockByNumber", "params": [hex(i), False]})
async with aiohttp.ClientSession() as session:
async with session.post('http://ubuntu18-1:8545', json=req) as resp:
print(resp.status)
print(await resp.text())
loop = asyncio.get_event_loop()
loop.run_until_complete(post_test())
我实际上得到了一个包含两个回复的列表,但状态是一个数字 200。这怎么可能? aiohttp 的文档从未提及发布列表的可能性。
举个例子:
#!/usr/bin/env python
# Python3.9+
import aiohttp
import anyio # pip install anyio
def get_request_list() -> list[dict]:
req: list[dict] = []
for idx, i in enumerate(range(15544190, 15544192), 1):
req.append(
{
"jsonrpc": "2.0",
"id": idx,
"method": "eth_getBlockByNumber",
"params": [hex(i), False],
}
)
return req
async def http_post(
session: aiohttp.ClientSession, payload: dict, url="http://ubuntu18-1:8545"
) -> tuple[int, str]:
async with session.post(url, json=payload) as resp:
resp_text = await resp.text()
return resp.status, resp_text
async def test_aiohttp() -> list[tuple[int, str]]:
request_list = get_request_list()
response_list: list[tuple[int, str]] = [(0, "")] * len(request_list)
async def runner(coro, i):
response_list[i] = await coro
async with aiohttp.ClientSession() as session:
async with anyio.create_task_group() as tg:
for idx, req in enumerate(request_list):
coro = http_post(session, req)
tg.start_soon(runner, coro, idx)
return response_list
async def main():
responses = await test_aiohttp()
for status_code, resp_text in responses:
print(f"{status_code = }")
print(f"{resp_text[:200] = }")
if __name__ == "__main__":
anyio.run(main)