use doctest and logging in python program

扶醉桌前 提交于 2019-12-04 11:08:57

I'm not sure why you want to do this, but if you really need to do it, then you can define your own subclass of DocTestRunner, and override the run method:

#imports left out, code not tested - just to point you in the right direction
class MyDocTestRunner(DocTestRunner):
    def run(self, test, compileflags=None, out=None, clear_globs=True):
        if out is None:
            handler = None
        else:
            handler = StreamHandler(out)
        logger = logging.getLogger() # root logger (say)
        if handler:
            logger.addHandler(handler)
        try:
            DocTestRunner.run(self, test, compileflags, out, clear_globs)
        finally:
            if handler:
                logger.removeHandler(handler)
                handler.close()

Then use this runner in place of DocTestRunner.

Within your doctest, before any logging capture is needed, do a addHandler(logging.Streamhandler(sys.stdout)) on your logger.

For example, assuming loggeris your logging object:

"""
This is a doctest that will capture output from the logging module.

>>> logger.addHandler(logging.StreamHandler(sys.stdout))

The rest of your doctest, now able to use output from the logging
module...
"""

Explanation: Once the doctest is running, doctest has already put its spoof in place, so sys.stdout is now set to DocTestRunner._fakeout. If you create a logging.StreamHandler for sys.stdout at this point, sys.stdout will point to doctest's spoof for sys.stdout rather than the real sys.stdout.

This solution also has the advantage not depending on internal private variables in doctest, such as _fakeout or _SpoofOut, in case they change in the future.

Gotchas: If you get

error: [Errno 128] Transport endpoint is not connected

you might have forgotten to import sys.

One simple and general-purpose approach looks like this:

LOGGER = logging.getLogger(__name__)
if hasattr(sys.modules['__main__'], '_SpoofOut'):
    LOGGER.setLevel(logging.DEBUG)
    LOGGER.addHandler(logger.addHandler(logging.StreamHandler()))

The _SpoofOut attribute is injected by the doctest module. If it's present, you can configure logging specifically for doctest. E.g. in my example, set a verbose debug mode and log to the console.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!