Asyncio 结合自定义模块和 aiohttp
Asyncio combined with custom modules and aiohttp
我正在尝试让模块休眠几秒钟,在休眠期间,脚本应该继续 运行。
当睡眠结束时,模块应该放置 data["found"] = True
,但代码永远不会超过 asyncio.sleep()
代码应打印:
- “珍珠龙”
- “做事” x 5
- “珍珠龙”
但是球蛙再也没有回来。
main.py:
# main.py
urls = {"pokemon": pokemon.data, "nba": nba.data}
async def get_data(session, url):
async with session.get(url, headers=headers) as r:
return await r.json()
async def execute_modules(data):
if pokemon.data["found"]:
asyncio.create_task(nba.find_name(data[0]))
else:
asyncio.create_task(pokemon.find_name(data[0]))
asyncio.create_task(nba.find_name(data[1]))
async def main():
async with aiohttp.ClientSession() as session:
tasks = []
for key, value in urls.items():
if not value["found"]:
tasks.append(asyncio.create_task(get_data(session, value["url"])))
data = await asyncio.gather(*tasks)
# print(data[1])
await execute_modules(data)
if __name__ == "__main__":
while True:
asyncio.run(main())
time.sleep(2)
pokemon.py:
import asyncio
data = {
"url": "https://pokeapi.co/api/v2/pokemon/1",
"found": False
}
async def find_name(pokemon):
if pokemon["name"] == "bulbasaur":
data["found"] = True
print("bulbasaur found")
await asyncio.sleep(10)
data["found"] = False
else:
print("no bulbasaur")
nba.py
data = {
"url": "https://www.balldontlie.io/api/v1/players/1",
"found": False
}
async def find_name(nba):
print("do stuff")
问题出在execute_models()
。在那里你产生 1-2 个任务但永远不会等待它们完成。
这意味着该任务被安排到 运行 下一个事件循环迭代,但不会再有另一个事件循环迭代,因为在生成任务后您永远不会 await
任何东西。所以 main()
退出并且 asyncio.run()
取消所有剩下的任务。您需要做的是在 execute_models()
中使用 asyncio.gather()
或让 execute_models()
return 它创建的任务并将另一个 asyncio.gather()
放入 main()
.
async def execute_modules(data):
tasks = []
if pokemon.data["found"]:
tasks.append(asyncio.create_task(nba.find_name(data[0])))
else:
tasks.append(asyncio.create_task(pokemon.find_name(data[0])))
tasks.append(asyncio.create_task(nba.find_name(data[1])))
await asyncio.gather(*tasks)
由于您似乎希望脚本继续 运行ning 而不是等待睡眠,您可能希望将 while True
循环放在 main()
内并更改 time.sleep(2)
到 asyncio.sleep(2)
而不是我上面建议的。
这里的重要方面是事件循环保持活动状态,这样任务就不会被取消并继续 运行。
我正在尝试让模块休眠几秒钟,在休眠期间,脚本应该继续 运行。
当睡眠结束时,模块应该放置 data["found"] = True
,但代码永远不会超过 asyncio.sleep()
代码应打印:
- “珍珠龙”
- “做事” x 5
- “珍珠龙”
但是球蛙再也没有回来。
main.py:
# main.py
urls = {"pokemon": pokemon.data, "nba": nba.data}
async def get_data(session, url):
async with session.get(url, headers=headers) as r:
return await r.json()
async def execute_modules(data):
if pokemon.data["found"]:
asyncio.create_task(nba.find_name(data[0]))
else:
asyncio.create_task(pokemon.find_name(data[0]))
asyncio.create_task(nba.find_name(data[1]))
async def main():
async with aiohttp.ClientSession() as session:
tasks = []
for key, value in urls.items():
if not value["found"]:
tasks.append(asyncio.create_task(get_data(session, value["url"])))
data = await asyncio.gather(*tasks)
# print(data[1])
await execute_modules(data)
if __name__ == "__main__":
while True:
asyncio.run(main())
time.sleep(2)
pokemon.py:
import asyncio
data = {
"url": "https://pokeapi.co/api/v2/pokemon/1",
"found": False
}
async def find_name(pokemon):
if pokemon["name"] == "bulbasaur":
data["found"] = True
print("bulbasaur found")
await asyncio.sleep(10)
data["found"] = False
else:
print("no bulbasaur")
nba.py
data = {
"url": "https://www.balldontlie.io/api/v1/players/1",
"found": False
}
async def find_name(nba):
print("do stuff")
问题出在execute_models()
。在那里你产生 1-2 个任务但永远不会等待它们完成。
这意味着该任务被安排到 运行 下一个事件循环迭代,但不会再有另一个事件循环迭代,因为在生成任务后您永远不会 await
任何东西。所以 main()
退出并且 asyncio.run()
取消所有剩下的任务。您需要做的是在 execute_models()
中使用 asyncio.gather()
或让 execute_models()
return 它创建的任务并将另一个 asyncio.gather()
放入 main()
.
async def execute_modules(data):
tasks = []
if pokemon.data["found"]:
tasks.append(asyncio.create_task(nba.find_name(data[0])))
else:
tasks.append(asyncio.create_task(pokemon.find_name(data[0])))
tasks.append(asyncio.create_task(nba.find_name(data[1])))
await asyncio.gather(*tasks)
由于您似乎希望脚本继续 运行ning 而不是等待睡眠,您可能希望将 while True
循环放在 main()
内并更改 time.sleep(2)
到 asyncio.sleep(2)
而不是我上面建议的。
这里的重要方面是事件循环保持活动状态,这样任务就不会被取消并继续 运行。