如何在ipython会话中完全重置Python stdlib日志模块?

7 投票
1 回答
2581 浏览
提问于 2025-04-16 15:54

我想在ipython会话中多次调用Python脚本,使用%run命令,并且希望每次调用这些脚本时能够根据通过%run传递的命令行参数进行日志记录。

举个例子,当我在调试cmd.py时,可能会想要多次运行:

%run cmd.py
... logs with default behavior, e.g. to STDERR with root level WARN

%run cmd.py --log_level DEBUG --log_file /tmp/cmd.out
... logs with root level DEBUG to a file

%run cmd.py --log_level ERROR

不过,这有点麻烦,因为使用logging.basicConfig设置的日志状态在第一次%run命令执行后会一直保留(这对于所有模块来说都是这样,通常在使用%run时也是希望如此)。

我明白,像上面那样一系列的%run命令并不等同于在新进程中运行每个命令。但是,如果能够重新初始化一些设置,比如日志级别和日志文件,那就方便多了。

我在cmd.py中尝试过类似这样的代码:

import logging_config  # parse logging config from sys.argv
reload(logging_config) # re-parse cmdline if using %run multiple times

而logging_config.py的内容是(简化版):

if logging_initialized:
    logging.getLogger().setLevel(lvl)
else:
    logging.basicConfig(level=lvl)
    logging_initialized = True

在简单的情况下,这个方法是有效的,但如果cmd.py导入了也使用日志的库,就不行了。我还尝试在每次cmd.py结束时调用logging.shutdown(),但似乎没有什么帮助。

1 个回答

4

不要用 basicConfig() 这种方式来配置日志,因为它主要是用来做简单的一次性设置的。就像文档里说的,第一次调用后再调用是没有效果的(只有在根日志器没有处理器时才会有效)。如果你的脚本是在命令行下运行,这样做没问题,但如果是在交互式解释器、IPython、IDLE、PythonWin 或其他类似的环境中,这种方式就不太合适,因为这些环境下的进程不会退出。

相反,你应该使用编程方式来配置,或者用 fileConfig()dictConfig(),这些方法可以完全用新的配置替换掉现有的日志配置。

撰写回答