问题描述:
一个使用 Apscheduler 定时启动 Aiohttp 下载文件的小工具,在不使用 apscheduler 的时候,可以正常工作。
使用 apscheduler 后则会类似出现以下错误:
loop = asyncio.get_event_loop()
File "/usr/local/python3.7.4/lib/python3.7/asyncio/events.py", line 644, in get_event_loop
% threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'ThreadPoolExecutor-0_1'.
在查看 get_event_loop 源码的时候,发现以下问题:
def get_event_loop():
"""Return an asyncio event loop.
When called from a coroutine or a callback (e.g. scheduled with call_soon
or similar API), this function will always return the running event loop.
If there is no running event loop set, the function will return
the result of `get_event_loop_policy().get_event_loop()` call.
"""
# NOTE: this function is implemented in C (see _asynciomodule.c)
current_loop = _get_running_loop()
if current_loop is not None:
return current_loop
return get_event_loop_policy().get_event_loop()
注释中很明确的说明:当从协程中调用时,此函数将始终返回正在运行的 loop, 而不是新建 Loop
至此异常根源明白:由于我是在 Apscheduler 线程中运行的 Loop 所以,在get_event_loop 时获取到的是 Apscheduler 的创建的线程,而 Apscheduler 的线程并不是一个loop 所以就会抛出以上错误。
解决办法:
很简单,修改成以下这样即可:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
显式设置一下事件循环即可。