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

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

问题描述

我想使用 asyncio 获取网页 html.

I would like to use asyncio to get webpage html.

我在 jupyter notebook 中运行以下代码:

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() 不能从正在运行的事件循环中调用

有什么问题?

如何解决?

推荐答案

asyncio.run() 文档说:

这个函数不能当另一个异步事件循环在同一线程中运行时调用.

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

就您而言,jupyter (IPython ≥ 7.0)已经在运行一个事件循环:

In your case, jupyter (IPython ≥ 7.0) is already running an event loop:

您现在可以在 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.

因此您无需自己启动事件循环,而是可以直接调用 await main(url),即使您的代码位于任何异步函数之外.

Therefore you don't need to start the event loop yourself and can instead call await main(url) directly, even if your code lies outside any asynchronous function.

Jupyter/IPython

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

Python (≥ 3.7)

import asyncio

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

在你的代码中:

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

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

注意

有一个轻微 与 IPython 相比,Jupyter 如何使用循环的差异.

There is a slight difference on how Jupyter uses the loop compared to IPython.

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

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