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

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

问题描述:

我正在尝试编写一个不和谐的机器人程序,它使用我从http休息调用中获取的数据更新用户。如何在asycio后台线程中使用aiohttp

由于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和异步函数很陌生。

我通过让另一个后台任务将http响应作为全局变量并自行更新来解决此问题。

我不确定这是我应该这样做的方式,但这就是让我走出泡菜的原因。

没有从aiohttp版本中得到的错误,很难猜测。但是一见钟情,我要说的是:

  • 无需显式传递事件循环ClientSession,它会自动选择当前事件循环,所以你应该叫​​
  • fetch功能不应该await respresp那里不是一个协程。你可能想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"]