
Python多进程环境下直接使用标准logging模块写入同一文件会导致日志错乱、内容覆盖或丢失,根本原因是多个进程同时操作文件句柄,缺乏跨进程同步机制。要实现进程安全的日志记录,核心思路是避免多个进程直接写同一文件,转而通过集中式日志收集或加锁机制来协调。
使用QueueHandler + QueueListener(推荐)
这是官方推荐的多进程日志方案:每个子进程将日志记录发送到一个multiprocessing.Queue,由单独的监听进程(通常在主进程中)从队列中消费并统一写入文件。这种方式天然规避了文件竞争,且保持日志顺序性(按入队顺序)。
- 主进程创建
Queue和QueueListener,启动监听器(自动调用handler.handle()) - 子进程初始化
QueueHandler,将其添加到根logger或自定义logger - 子进程调用
logging.info()等方法时,日志自动经队列转发至监听器处理 - 监听器中的handler可为
FileHandler、RotatingFileHandler等,支持滚动、编码、格式化
文件级加锁(简单场景可用)
若日志量不大、进程数少,可在每个写日志的操作前对文件加锁。注意必须使用multiprocessing.Lock或基于文件系统的锁(如portalocker),不能用threading.Lock(仅限线程内有效)。
- 每次写入前调用
lock.acquire(),写完后lock.release() - 推荐用上下文管理器:
with lock:确保异常时也能释放锁 - 缺点:锁粒度粗,高并发下性能下降明显;若进程崩溃未释放锁,可能造成死锁(需配合超时或信号处理)
按进程ID分离日志文件
不共享文件,每个进程写自己的日志文件(如app_12345.log),后续再合并分析。适合调试、短期运行或日志量小的场景。
立即学习“Python免费学习笔记(深入)”;
- 在子进程启动时,动态生成带
os.getpid()或current_process().pid的文件名 - 可配合
concurrent.futures.ProcessPoolExecutor的initializer统一配置logger - 优点是零冲突、无需额外同步逻辑;缺点是日志分散,实时追踪困难,需额外工具聚合
使用第三方日志服务(生产环境优选)
将日志输出到syslog、Redis、Kafka或云日志服务(如ELK、Loki、阿里云SLS),由专用采集器统一落盘。这类方案解耦彻底,扩展性强,也便于做日志分级、告警、审计。
- Python可用
python-syslog发往本地syslog;或用kafka-python推送到Kafka Topic - 注意序列化日志record对象(建议用
json.dumps+ 自定义LogRecord序列化器) - 需保障传输可靠性(如重试、缓冲、确认机制),避免日志丢失










