Asyncio 结合自定义模块和 aiohttp

Asyncio combined with custom modules and aiohttp

我正在尝试让模块休眠几秒钟,在休眠期间,脚本应该继续 运行。
当睡眠结束时,模块应该放置 data["found"] = True,但代码永远不会超过 asyncio.sleep()
代码应打印:

但是球蛙再也没有回来。

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) 而不是我上面建议的。

这里的重要方面是事件循环保持活动状态,这样任务就不会被取消并继续 运行。