Python logging搭配joblib多线程时日志文件为空的问题
多线程/多进程下logging写入文件为空的问题
问题现象
使用joblib.Parallel开启多任务(n_jobs=4)时,通过logging向文件写入日志,最终得到空文件;但n_jobs=1单线程执行时,日志能正常输出。
复现代码
import logging import time from joblib import Parallel, delayed def worker(index): time.sleep(0.5) logging.info('Hi from myfunc {}'.format(index)) time.sleep(0.5) def main(): logging.basicConfig(filename='multithread_test.log', level=logging.INFO, format='%(relativeCreated)6d %(threadName)s %(message)s') Parallel(n_jobs=4)(delayed(worker)(m) for m in range(1, 8)) if __name__ == '__main__': main()
单线程正常输出示例
1636 MainThread Hi from myfunc 1 2656 MainThread Hi from myfunc 2 3676 MainThread Hi from myfunc 3 4696 MainThread Hi from myfunc 4 5716 MainThread Hi from myfunc 5 6736 MainThread Hi from myfunc 6 7756 MainThread Hi from myfunc 7
原因分析
joblib.Parallel默认使用loky多进程后端(n_jobs>1时),而logging.basicConfig仅在主线程初始化日志配置,子进程不会继承主线程的日志处理器(handler),导致子进程中的logging.info没有输出目标,日志无法写入文件。
解决方案
方案1:强制使用线程后端
如果任务是IO密集型,适合用多线程,指定backend='threading'后,子线程会继承主线程的日志配置:
def main(): logging.basicConfig(filename='multithread_test.log', level=logging.INFO, format='%(relativeCreated)6d %(threadName)s %(message)s') # 指定线程后端 Parallel(n_jobs=4, backend='threading')(delayed(worker)(m) for m in range(1, 8))
方案2:子进程中重新初始化日志
若必须用多进程(CPU密集型任务),可在worker函数中重新配置日志:
def worker(index): # 子进程内单独初始化日志 logging.basicConfig(filename='multithread_test.log', level=logging.INFO, format='%(relativeCreated)6d %(threadName)s %(message)s') time.sleep(0.5) logging.info('Hi from myfunc {}'.format(index)) time.sleep(0.5)
注意:多进程直接写入同一文件可能出现内容覆盖,建议使用
logging.handlers.RotatingFileHandler等多进程安全的处理器,或给每个进程分配独立日志文件。
方案3:全局配置日志处理器
提前创建并配置日志处理器,添加到根logger,确保子进程继承配置:
def main(): # 创建文件处理器并设置格式 handler = logging.FileHandler('multithread_test.log') formatter = logging.Formatter('%(relativeCreated)6d %(threadName)s %(message)s') handler.setFormatter(formatter) # 配置根logger root_logger = logging.getLogger() root_logger.setLevel(logging.INFO) root_logger.addHandler(handler) Parallel(n_jobs=4)(delayed(worker)(m) for m in range(1, 8))
内容的提问来源于stack exchange,提问作者Mehmet Fide
相关产品推荐
相关产品推荐

