You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决asyncio嵌套函数中的“This event loop is already running”错误

解决异步爬虫嵌套事件循环报错的方案

这个问题的核心在于你在已经运行的事件循环中再次调用了loop.run_until_complete()——asyncio不允许嵌套启动事件循环,这就是报错的原因。同时你内层函数的写法没利用好asyncio的原生异步机制,导致移除run_until_complete()后无法等待任务完成。下面是具体的修正方案和优化建议:


1. 修正内层异步函数

内层的f函数不需要手动获取事件循环并调用run_until_complete(),直接用await等待子任务集合即可,因为此时事件循环已经在main函数中运行,所有协程会被自动调度到同一个循环里。

修正后的f函数:

async def f(category, total):
    # 生成当前分类下的所有URL(假设原代码的t_list是total的元素,这里修正变量名对应)
    urls = [urls_template[category].format(t) for t in total]
    # 直接等待所有子任务完成,无需额外启动事件循环
    result = await asyncio.gather(*map(parseURL_async, urls))
    return result

2. 修正并优化main函数

原代码里存在变量名错误(比如把函数f覆盖成了task对象),同时推荐用更简洁的方式管理事件循环:

方式一:兼容Python 3.6及以下(手动管理loop)

def main():
    loop = asyncio.get_event_loop()
    # 修正变量名,避免覆盖原函数f
    task_p = loop.create_task(f("p", all_p_list))
    task_f = loop.create_task(f("f", all_f_list))
    # 等待所有外层任务完成
    loop.run_until_complete(asyncio.gather(task_p, task_f))
    # 如果需要获取返回结果,可以改为:
    # result_p, result_f = loop.run_until_complete(asyncio.gather(task_p, task_f))

方式二:Python 3.7+推荐写法(用asyncio.run())

asyncio.run()会自动创建、运行和关闭事件循环,代码更简洁安全:

async def main():
    # 创建异步任务
    task_p = asyncio.create_task(f("p", all_p_list))
    task_f = asyncio.create_task(f("f", all_f_list))
    # 等待所有任务完成
    await asyncio.gather(task_p, task_f)

if __name__ == "__main__":
    asyncio.run(main())

额外优化建议

如果你的parseURL_async是基于同步请求库(比如requests)实现的,那其实并没有真正的异步能力。建议改用aiohttp这类异步HTTP库,才能真正发挥asyncio的并发优势,示例如下:

import aiohttp

async def parseURL_async(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            # 假设你需要解析HTML,这里可以用BeautifulSoup处理
            html = await resp.text()
            return html  # 返回解析后的结果

内容的提问来源于stack exchange,提问作者Blaszard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:05:25