如何处理 asyncio 中嵌套函数的 "This event loop is already running" 错误?
How can I deal with "This event loop is already running" error on a nested function in asyncio?
我想用一组类别执行网络抓取,每个类别也有一个 URL 的列表。所以我决定在main函数中只根据每个类别调用一个函数,并且在inner函数内部有一个非阻塞调用。
代码如下:
def main():
loop = asyncio.get_event_loop()
b = loop.create_task(f("p", all_p_list))
f = loop.create_task(f("f", all_f_list))
loop.run_until_complete(asyncio.gather(p, f))
它应该同时执行f
函数。
但是 f
函数也必须 运行 循环,因为在函数中它同时调用一个函数,基于每个 URL.
async def f(category, total):
urls = [urls_template[category].format(t) for t in t_list]
soups_coro = map(parseURL_async, urls)
loop = asyncio.get_event_loop()
result = await loop.run_until_complete(asyncio.gather(*soups_coro))
但是在我运行这个脚本之后,它得到了一个This event loop is already running
错误,我发现这是因为我在内部和外部函数中都调用了loop.run_until_complete()
。
然而,当我剥离 run_until_complete()
,并在 main()
中调用 f()
时,函数调用立即完成,它不能等待内部函数完成。所以在main()
中调用循环是不可避免的。但后来我认为它与内部函数不兼容,内部函数也必须调用它。
如何处理问题和 运行 循环?原始代码都在同一个 main()
中并且有效,但我想尽可能使其更清晰。
How can I deal with the problem and run the loop?
循环已经运行宁。您不需要(也不能)再次 运行 它。
result = await loop.run_until_complete(asyncio.gather(*soups_coro))
你等错了。 loop.run_until_complete
没有 return 你可以等待的东西 (a Future
);它 return 是你 运行 直到完成的任何结果。
当您直接调用 f
时似乎没有任何反应的原因是 f
是一个 asyncio 风格的协程。因此,它 return 是一个必须用事件循环安排的未来。它不会执行,直到 运行ning 事件循环告诉它执行。 loop.run_until_complete
会为您处理所有这些。
要结束您的问题,您需要等待 asyncio.gather
。
async def f(category, total):
urls = [urls_template[category].format(t) for t in t_list]
soups_coro = map(parseURL_async, urls)
result = await asyncio.gather(*soups_coro)
您可能还想在 f
的末尾包含 return result
。
将main()
转换为async函数,由loop.run_until_complete()
执行。
当代码只有一个时 run_until_complete()
-- 一切都变得容易多了。在 Python 3.7 中,您将可以只写 asyncio.run(main())
我想用一组类别执行网络抓取,每个类别也有一个 URL 的列表。所以我决定在main函数中只根据每个类别调用一个函数,并且在inner函数内部有一个非阻塞调用。
代码如下:
def main():
loop = asyncio.get_event_loop()
b = loop.create_task(f("p", all_p_list))
f = loop.create_task(f("f", all_f_list))
loop.run_until_complete(asyncio.gather(p, f))
它应该同时执行f
函数。
但是 f
函数也必须 运行 循环,因为在函数中它同时调用一个函数,基于每个 URL.
async def f(category, total):
urls = [urls_template[category].format(t) for t in t_list]
soups_coro = map(parseURL_async, urls)
loop = asyncio.get_event_loop()
result = await loop.run_until_complete(asyncio.gather(*soups_coro))
但是在我运行这个脚本之后,它得到了一个This event loop is already running
错误,我发现这是因为我在内部和外部函数中都调用了loop.run_until_complete()
。
然而,当我剥离 run_until_complete()
,并在 main()
中调用 f()
时,函数调用立即完成,它不能等待内部函数完成。所以在main()
中调用循环是不可避免的。但后来我认为它与内部函数不兼容,内部函数也必须调用它。
如何处理问题和 运行 循环?原始代码都在同一个 main()
中并且有效,但我想尽可能使其更清晰。
How can I deal with the problem and run the loop?
循环已经运行宁。您不需要(也不能)再次 运行 它。
result = await loop.run_until_complete(asyncio.gather(*soups_coro))
你等错了。 loop.run_until_complete
没有 return 你可以等待的东西 (a Future
);它 return 是你 运行 直到完成的任何结果。
当您直接调用 f
时似乎没有任何反应的原因是 f
是一个 asyncio 风格的协程。因此,它 return 是一个必须用事件循环安排的未来。它不会执行,直到 运行ning 事件循环告诉它执行。 loop.run_until_complete
会为您处理所有这些。
要结束您的问题,您需要等待 asyncio.gather
。
async def f(category, total):
urls = [urls_template[category].format(t) for t in t_list]
soups_coro = map(parseURL_async, urls)
result = await asyncio.gather(*soups_coro)
您可能还想在 f
的末尾包含 return result
。
将main()
转换为async函数,由loop.run_until_complete()
执行。
当代码只有一个时 run_until_complete()
-- 一切都变得容易多了。在 Python 3.7 中,您将可以只写 asyncio.run(main())