首页 文章

如何在asycio后台线程中使用aiohttp

提问于
浏览
0

我正在尝试编写一个不和谐机器人,用来从http休息调用中获取的数据更新用户 .

由于discord.py使用asyncio,我想我会尝试通过这种方法 .

async def my_background_task():

    print("starting BG task")
    await client.wait_until_ready()
    while not client.is_closed:
        requests.get(getMyUrl()).json()["dict_element"]
        #do more stuff

client.loop.create_task(my_background_task())
client.run("api key goes here")

使用同步“请求”库可以直截了当 . 但是我可以运行它几个小时直到它崩溃 . 我假设因为'请求'未能完成无限循环 .

async def fetch(session, url):
    async with session.get(url) as resp:
        print(resp.status)
        return await resp

async def fetch_url(loop, url):
    async with aiohttp.ClientSession(loop=loop) as session:
        await fetch(session, url)

async def my_method(url):

    loop = asyncio.get_event_loop()
    return loop.run_until_complete(fetch_url(loop,url))

async def my_background_task():

    print("starting BG task")
    await client.wait_until_ready()
    while not client.is_closed:
        await my_method.("www.theinternet.com/restcall").json()["dict_element"]
        #do more stuff

所以我现在尝试使用aiohttp,但在此循环中遇到异步循环问题 .

我还没有找到关于如何解决这个问题的正确解释 . 我是python和异步函数的新手 .

2 回答

  • 1

    如果没有您从aiohttp版本获得的错误,很难猜到 . 但乍一看,我会说:

    • 无需将事件循环显式传递给 ClientSession ,它会自动选择当前事件循环,因此您只需调用 ClientSession()

    • fetch 函数不应 await resp . resp 不是那里的协程 . 您可能想 return await resp.json() (并删除 my_background_task 中的额外 .json()

    • my_method 中,您已经在协程中运行,如 async def 所示 . 所以要调用另一个协同程序,你应该 await -ing它,而不是创建一个新的事件循环并在新的循环中运行它 .

    • my_background_task 中,您正在等待一些没有任何意义的事情:检查await的操作员优先级,您在协程上调用 .__getitem__ ,然后等待 __getitem__ 的结果,这与您想要的相反 .

    • 仍然在那一行,你不能在响应关闭后尝试读取响应的json主体(响应在你退出 async with 时立即关闭,即只要 fetch 方法完成) .

    • 最后,您不应该在每个循环中重新创建ClientSession . 这是存在的,因此它可以在请求之间共享,因此您应该在 my_background_task 中创建一次并使用它

    async def fetch(session, url):
        async with session.get(url) as resp:
            print(resp.status)
            return await resp.json()
    
    async def my_background_task()
        print("starting BG task")
        await client.wait_until_ready()
        async with aiohttp.ClientSession() as session:
            while not client.is_closed:
                data = await fetch(session, "www.theinternet.com/restcall")
                element = data["dict_element"]
    
  • 0

    我通过另一个后台任务来解决这个问题,该任务将http响应保持为全局变量并自行更新 .

    我不确定这是不是我应该这样做的方式,但这就是让我脱离泡菜的原因 .

相关问题