为了账号安全,请及时绑定邮箱和手机立即绑定

asyncio.run() 不能从正在运行的事件循环中调用

asyncio.run() 不能从正在运行的事件循环中调用

慕婉清6462132 2021-12-21 15:56:26
我想使用 asyncio 来获取网页 html。我在 jupyter notebook 中运行以下代码:import aiofilesimport aiohttpfrom aiohttp import ClientSessionasync 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问题是什么?如何解决?
查看完整描述

2 回答

?
拉莫斯之舞

TA贡献1820条经验 获得超10个赞

asyncio.run()文件说:

当另一个异步事件循环在同一线程中运行时,无法调用此函数。

在您的情况下,jupyter(IPython ≥ 7.0)已经在运行事件循环:

您现在可以在 IPython 终端和笔记本中的顶层使用 async/await,它应该——在大多数情况下——“正常工作”。将 IPython 更新到版本 7+,将 IPykernel 更新到版本 5+,然后您就可以参加比赛了。

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

Jupyter/IPython

async def main():

    print(1)

    

await main()

蟒蛇 (≥ 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 使用循环的方式略有不同


查看完整回答
反对 回复 2021-12-21
?
跃然一笑

TA贡献1826条经验 获得超6个赞

要添加 tocglacet的答案 - 如果想要检测循环是否正在运行并自动调整(即main()在现有循环上运行,否则asyncio.run()),这里是一个可能有用的片段:


# async def main():

#     ...


try:

    loop = asyncio.get_running_loop()

except RuntimeError:  # 'RuntimeError: There is no current event loop...'

    loop = None


if loop and loop.is_running():

    print('Async event loop already running. Adding coroutine to the event loop.')

    tsk = loop.create_task(main())

    # ^-- https://docs.python.org/3/library/asyncio-task.html#task-object

    # Optionally, a callback function can be executed when the coroutine completes

    tsk.add_done_callback(

        lambda t: print(f'Task done with result={t.result()}  << return val of main()'))

else:

    print('Starting new event loop')

    asyncio.run(main())


查看完整回答
反对 回复 2021-12-21
  • 2 回答
  • 0 关注
  • 1170 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信