Django 跑单元测试时如何禁用日志输出?
Django 测试时静音日志的三种方式:logging.disable(logging.CRITICAL) 全局开关、在 settings.py 中判断 test 命令自动禁用、用 logging filter 精细控制。
最快的方式是在 settings.py 里判断是否在跑测试:如果是 manage.py test 启动,就执行 logging.disable(logging.CRITICAL),全局静音;之后 Django 测试运行器输出的错误信息不受影响。
方法一:settings.py 自动判断(推荐)
import sys
import logging
if len(sys.argv) > 1 and sys.argv[1] == 'test':
logging.disable(logging.CRITICAL)
sys.argv[1] == 'test' 表示当前命令是 manage.py test。这样平时开发日志照常,跑测试时自动安静,无需手动切换。
方法二:测试代码里手动禁用
在测试基类或 setUp 中:
import logging
logging.disable(logging.CRITICAL)
# 测试结束后恢复
logging.disable(logging.NOTSET)
方法三:logging filter 精细控制
在 settings.py 的 LOGGING 配置中自定义 filter,只过滤特定 logger 或特定消息,而不是全局静音:
LOGGING = {
'version': 1,
'filters': {
'no_sql': {
'()': 'django.utils.log.CallbackFilter',
'callback': lambda r: 'django.db.backends' not in r.name,
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'filters': ['no_sql'],
},
},
# ...
}
适合只想屏蔽 SQL 日志等特定噪音的场景。
常见问题(FAQ)
Q:禁用日志后测试失败时还看得到报错吗?
A:看得到。测试框架自身的断言输出不走 logging 模块,logging.disable 只影响 logging 产生的消息。
Q:Django 测试默认会怎么处理 logging?
A:Django 测试运行器默认不重置 LOGGING 配置(除非设了 LOGGING_CONFIG),但 DEBUG 为 False 时行为与开发环境不同,SQL 日志默认不输出。
Q:想断言"某处确实打了日志"怎么办?
A:用 self.assertLogs('logger名', level='INFO') 上下文管理器,这是 Django/Python 测试断言日志的标准方式,静音全局日志不影响它工作。