记一个在docker中运行多线程event_loop.run_forever()的bug

时间:2023-03-10 02:11:37
记一个在docker中运行多线程event_loop.run_forever()的bug

问题简介

我写爬虫,用到了asyncio相关的事件循环,新建了一个线程去run_forever(),在docker中运行。后来程序有异常,主线程挂了,但是竟然不报错。查了很久,才找出来。

如果你新建一个线程去运行一般的死循环,主线程出错退出,是会报错的,虽然子线程还会继续运行。

如果你新建一个线程去运行event_loop.run_forever(),主线程出异常退出,没有任何错误提示,子线程一样继续运行。

解决办法

我查了很久也不知道为什么,在本地跑,一切正常。测试程序如下:

import asyncio
import logging
from threading import Thread logging.basicConfig(level=logging.INFO, format='[%(asctime)s] - %(levelname)s in %(filename)s: %(message)s')
logger = logging.getLogger(__name__) def start_loop(event_loop):
"""start run_forever"""
asyncio.set_event_loop(event_loop)
event_loop.run_forever() def get_event_loop():
"""new and return event_loop"""
event_loop = asyncio.new_event_loop()
t0 = Thread(target=start_loop, args=(event_loop,))
t0.start()
return event_loop if __name__ == '__main__':
loop = get_event_loop() logger.info('make error')
raise TimeoutError('sfasf') """
[2019-04-16 13:40:46,101] - INFO in docker_test.py: make error
Traceback (most recent call last):
File "D:/Code/python/concurrent_crawler/test/docker_test/docker_test.py", line 38, in <module>
raise TimeoutError('sfasf')
TimeoutError: sfasf
"""

如果在docker中就没有任何错误提示,最后解决办法如下

import asyncio
import logging
from threading import Thread logging.basicConfig(level=logging.INFO, format='[%(asctime)s] - %(levelname)s in %(filename)s: %(message)s')
logger = logging.getLogger(__name__) def start_loop(event_loop):
"""start run_forever"""
asyncio.set_event_loop(event_loop)
event_loop.run_forever() def get_event_loop():
"""new and return event_loop"""
event_loop = asyncio.new_event_loop()
t0 = Thread(target=start_loop, args=(event_loop,))
t0.setDaemon(True) # 随着主线程结束而结束
t0.start()
return event_loop if __name__ == '__main__':
loop = get_event_loop() logger.info('make error')
raise TimeoutError('sfasf')

利用线程的setDaemon(True)方法,结束子线程。这样才会输出出来!

这个问题我放到*了link

相关文章