如何将stdlib日志与py.test结合?
我正在使用py.test来测试我的一些模块,这些模块里面有很多标准库的日志记录功能。我希望这些日志能够输出到标准输出(stdout),这样py.test就能捕捉到这些信息,这样如果测试失败,我就能看到所有相关的日志信息。
问题是,日志模块在尝试记录信息的时候,往往是在py.test已经丢弃了这个标准输出对象之后。这就导致我遇到了以下问题:
Traceback (most recent call last):
File "/usr/lib/python2.6/atexit.py", line 24, in _run_exitfuncs
func(*targs, **kargs)
File "/usr/lib/python2.6/logging/__init__.py", line 1508, in shutdown
h.flush()
File "/usr/lib/python2.6/logging/__init__.py", line 754, in flush
self.stream.flush()
ValueError: I/O operation on closed file
如果我用-s
参数关闭捕捉功能,就没有问题了,但这样一来,测试输出就会变得很乱,因为会有很多不相关的日志信息。
有没有人能告诉我,如何正确地将标准库的日志记录和py.test结合起来呢?
(我试着查看了这个链接,看起来应该没有问题,但对我帮助不大)
3 个回答
你只需要在运行py.test的时候加上 -s
这个选项,这样它就不会把输出的内容给捕捉起来了。
如果你不介意在对象被py.test丢弃后,日志记录没有去处,你可以在你的模块或测试的早期设置一个模块级别的变量 logging.raiseExceptions
为 False
。
这样做会让日志模块忽略在日志系统中发生的异常。(这也是在生产环境中一个好的做法,因为你不希望日志中的错误导致系统崩溃)
你还可以使用 logging.basicConfig()
将日志输出设置到一个单独的文件中。但这可能不是你想要的。
记录和捕捉交互的功能是为了更好地配合即将发布的2.0.1版本。你可以通过以下方式安装这个开发版本快照:
pip install -i http://pypi.testrun.org pytest
在你输入“py.test --version”后,应该能看到至少是“2.0.1.dev9”的版本号。而你之前提到的问题或错误应该也解决了。
简单说一下背景:logging这个包会“占有”它使用的流,默认情况下它会抓取sys.stderr,并在程序退出时关闭它,这个过程是通过一个叫做atexit的模块来注册的。py.test会用一个临时文件替代sys.stdout,以便能够记录输出(包括文件描述符级别的输出,这样也能捕捉到子进程的输出)。因此,py.test变得非常小心,始终使用同一个临时文件,以免logging的atexit代码出现问题。
另外,你还可以安装[pytest-capturelog][1]这个插件,它能更好地帮助你处理日志输出。