我的程序使用了gevent patch,但是在程序中,我需要在子线程中执行asyncio相关的代码 当多个子线程执行同一个协程时,会触发“RuntimeError:此事件循环已在运行” 它们是不同的线程,我为每个子线程生成了自己的事件循环,我无法理解这个问题 当我注释掉猴子补丁时,程序按照我的预期执行了
ERROR:root:This event loop is already running
Traceback (most recent call last):
File "/Users/computer1/pytest/test.py", line 30, in func1
loop.run_until_complete(asyncf1())
File "/opt/homebrew/Cellar/[email protected]/3.9.18_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 623, in run_until_complete
self._check_running()
File "/opt/homebrew/Cellar/[email protected]/3.9.18_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 583, in _check_running
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
/Users/computer1/pytest/test.py:32: RuntimeWarning: coroutine 'asyncf1' was never awaited
logging.error(e, exc_info=True)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
ERROR:root:This event loop is already running
Traceback (most recent call last):
File "/Users/computer1/pytest/test.py", line 30, in func1
loop.run_until_complete(asyncf1())
File "/opt/homebrew/Cellar/[email protected]/3.9.18_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 623, in run_until_complete
self._check_running()
File "/opt/homebrew/Cellar/[email protected]/3.9.18_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 583, in _check_running
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
import logging
import gevent.monkey
gevent.monkey.patch_all()
import concurrent.futures
import threading
import time
import asyncio
pool = concurrent.futures.ThreadPoolExecutor()
async def asyncf1():
print("aa")
def func1():
# print(f"thread:{threading.get_ident()},gevent:{id(gevent.getcurrent())}")
try:
try:
loop = asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
# asyncio.set_event_loop(loop)
loop.run_until_complete(asyncf1())
except Exception as e:
logging.error(e, exc_info=True)
print(threading.current_thread())
time.sleep(3)
for i in range(3):
pool.submit(func1)
time.sleep(10)
是否有强烈需要混合
gevent
和asyncio
?据我所知,它们是针对类似问题的两种不同的解决方案。我不太清楚它们是否可以轻松混合。但看来你的问题与gevent
无关。
据我所知,您的问题是您实际上并没有(至少总是)在自己的线程上启动
asyncio
事件循环。您将您的 func1
提交到线程 pool,而不一定是单独的、唯一的线程。我想你不会每次都会遇到这个错误,因为这取决于线程池如何在每次 for 循环迭代中将 func1
分配给线程。可能还有一些竞争条件。
asyncio
事件循环必须位于其自己的线程上,并且在事件循环期间它实际上拥有整个线程。因此,您应该为要运行的每个事件循环显式创建一个线程。
请参阅这些答案:
最后,目前尚不清楚您需要多个事件循环而不是仅使用一个事件循环。多个事件循环(因此多个线程)将比单个事件循环(因此单个线程)慢,并且我看不到多个事件循环有任何实际好处。