如何将stdlib日志与py.test结合?

5 投票
3 回答
1651 浏览
提问于 2025-04-16 10:11

我正在使用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 个回答

-1

你只需要在运行py.test的时候加上 -s 这个选项,这样它就不会把输出的内容给捕捉起来了。

3

如果你不介意在对象被py.test丢弃后,日志记录没有去处,你可以在你的模块或测试的早期设置一个模块级别的变量 logging.raiseExceptionsFalse

这样做会让日志模块忽略在日志系统中发生的异常。(这也是在生产环境中一个好的做法,因为你不希望日志中的错误导致系统崩溃)

你还可以使用 logging.basicConfig() 将日志输出设置到一个单独的文件中。但这可能不是你想要的。

6

记录和捕捉交互的功能是为了更好地配合即将发布的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]这个插件,它能更好地帮助你处理日志输出。

[1] http://pypi.python.org/pypi/pytest-capturelog/0.7

撰写回答