日志不输出但程序没报错的根源是配置未生效:默认根logger级别为warning,info及以下被过滤;多进程共用filehandler会导致写入冲突;uvicorn会重置root logger;缺失contextvars或loggeradapter则无法注入trace_id等上下文字段。

日志不输出但程序没报错
这是最典型的“日志丢失”假象:代码里写了 logging.info(),控制台或文件却空空如也。根本原因不是日志被丢弃,而是日志级别、处理器或根 logger 配置没生效。
常见错误现象:logging.debug() 完全静默;logging.info() 在脚本里能打,在 Flask/FastAPI 里消失;加了 FileHandler 却没生成日志文件。
- 检查是否调用了
logging.basicConfig()—— 如果没调用,且没手动配置root logger,默认级别是WARNING,INFO及以下全被过滤 - 确认有没有其他库(比如
requests、urllib3)调用了logging.getLogger().setLevel(),悄悄改掉了根 logger 级别 - 如果用了多个
Logger实例,注意propagate=True(默认值)会让日志向上冒泡到 root,可能被 root 的 handler 重复处理或拦截
多进程下文件日志写入失败或内容错乱
FileHandler 本身不支持多进程安全写入。当多个子进程同时打开同一个日志文件,会出现覆盖、截断、部分写入丢失等问题,尤其在 Linux 上更隐蔽。
使用场景:用 multiprocessing 启动 worker,每个 worker 都想往 app.log 写;或者用 gunicorn 多 worker 模式跑 Flask。
立即学习“Python免费学习笔记(深入)”;
- 绝对不要让多个进程共用同一个
FileHandler实例 —— 即使你只在主进程配置了一次,子进程 fork 后会继承 fd,但写入行为不可控 - 推荐方案:每个进程用独立日志文件,比如按 pid 命名:
app-{}.log.format(os.getpid()) - 若必须集中落盘,改用
RotatingFileHandler+delay=True并配合外部日志收集器(如rsyslog或filebeat),而非靠 Python 自身解决
异步框架(如 FastAPI + Uvicorn)中日志突然中断
Uvicorn 默认捕获并重置 root logger,导致你在 main.py 开头配好的 basicConfig 被清空。FastAPI 本身不接管日志,但运行时环境会干扰。
常见错误现象:本地 python main.py 日志正常,用 uvicorn main:app 就只输出 access log,你的 logging.info() 消失;或者只在第一次请求有日志,后续请求全无。
- 启动时加
--log-config参数指向 YAML/JSON 配置文件,而不是依赖代码里的basicConfig - 或者在
main.py中显式获取并配置logging.getLogger("uvicorn.access")和自定义 logger,避免和 uvicorn 冲突 - 注意
uvicorn的--reload模式会频繁重启进程,导致FileHandler被反复 open/close,容易触发权限或锁问题
日志内容里看不到 trace_id 或用户 ID 等上下文字段
这不是日志“丢失”,而是结构化上下文没注入到每条日志记录里。Python 的 Logger 默认不携带 request-scoped 数据,需要主动绑定。
使用场景:Web 请求中想让每条日志都带上 trace_id;Celery task 中想记录 task_id;CLI 工具中想加 user_name。
- 别用全局变量存上下文 —— 多线程/协程下会串数据;改用
threading.local()或contextvars.ContextVar(Python 3.7+) - 通过
LoggerAdapter注入字段,而不是每次logger.info("msg", extra={"trace_id": ...})手动传 - 确保 formatter 中包含对应字段,例如
"%(trace_id)s %(message)s",否则即使 extra 传了也显示不出来
复杂点在于 contextvars 在 asyncio task 切换时不会自动传播,Uvicorn 的 lifespan hook 或中间件里初始化后,还得显式在每个请求 handler 中 contextvar.set()。这点很容易被忽略,结果就是 80% 的请求有 trace_id,20% 是空的。










