无法从正在运行的事件循环中调用asyncio.run() [英] asyncio.run() cannot be called from a running event loop

查看:689
本文介绍了无法从正在运行的事件循环中调用asyncio.run()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用asyncio获取网页html.

I would like to use asyncio to get webpage html.

我在jupyter笔记本中运行以下代码:

I run the following code in jupyter notebook:

import aiofiles
import aiohttp
from aiohttp import ClientSession

async def get_info(url, session):
    resp = await session.request(method="GET", url=url)
    resp.raise_for_status()
    html = await resp.text(encoding='GB18030')
    with open('test_asyncio.html', 'w', encoding='utf-8-sig') as f:
        f.write(html)
    return html
    
async def main(urls):
    async with ClientSession() as session:
        tasks = [get_info(url, session) for url in urls]
        return await asyncio.gather(*tasks)

if __name__ == "__main__":
    url = ['http://huanyuntianxiazh.fang.com/house/1010123799/housedetail.htm', 'http://zhaoshangyonghefu010.fang.com/house/1010126863/housedetail.htm']
    result = asyncio.run(main(url))

但是,它返回RuntimeError: asyncio.run() cannot be called from a running event loop

出什么问题了?

如何解决?

推荐答案

此功能无法在同一线程中运行另一个异步事件循环时调用.

This function cannot be called when another asyncio event loop is running in the same thread.

您所遇到的问题是jupyter(IPython)已经在运行事件循环(对于 IPython≥7.0 ):

The problem in your case is that jupyter (IPython) is already running an event loop (for IPython ≥ 7.0):

您现在可以在IPython终端和笔记本电脑的顶层使用async/await,它应该-在大多数情况下-正常工作".将IPython更新到版本7+,将IPykernel更新到版本5+,然后您就可以开始比赛了.

You can now use async/await at the top level in the IPython terminal and in the notebook, it should — in most of the cases — "just work". Update IPython to version 7+, IPykernel to version 5+, and you’re off to the races.

这就是为什么您不需要在jupyter中自己启动事件循环,甚至可以在异步函数之外直接调用await main(url)的原因.

That's the reason why you don't need to start the event loop yourself in jupyter and you can directly call await main(url) even outside asynchronous functions.

在jupyter中

async def main():
    print(1)
    
await main()

使用普通Python(≥3.7)

import asyncio

async def main():
    print(1)
    
asyncio.run(main())

在您的代码中,将给出:

In your code that would give:

url = ['url1', 'url2']
result = await main(url)

for text in result:
    pass # text contains your html (text) response

这篇关于无法从正在运行的事件循环中调用asyncio.run()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆