FileHandler未向我想要的任何位置发送输出

0 投票
1 回答
1166 浏览
提问于 2025-04-17 17:30

这是我第一次玩日志模块。我有两个问题:

我找到的所有关于创建文件处理器的例子都用的是一个假文件名,但我想让我的日志文件有一个特定的标题格式。

log = time.strftime('./logs/'+'%H:%M:%S %d %b %Y', time.localtime())+'.log'
logger = logging.getLogger('myproject')
formatter = logging.Formatter('%(asctime)s %(message)s', '%H:%M:%S %d %b %Y')
handler = logging.FileHandler(log)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

一开始这看起来是有效的,因为日志文件确实被创建了,但当我结束脚本并检查它时,里面什么都没有。在你建议我使用 with open(log) as f: 之前,使用 f 替代 loghandler = logging.FileHandler(log) 中会给我错误,提示文件根本没有被创建。我到底做错了什么,导致日志文件没有写入?是因为我在文件名上想得太复杂了吗?

第二个问题可能和第一个有点关系。我真正想要的是能够同时写入控制台和日志文件,因为这个脚本运行时间很长,我想了解进度。我看到有一些关于如何做到这一点的答案,比如这里,但这些似乎都假设我想为两个不同的输出设置不同的日志级别;其实我并不想。顺便说一下,我确实意识到如果我的脚本没有动态生成日志文件的名字,我可以用 python myscript.py | tee log.file 来避免创建不同的处理器。

我觉得我在回答第二个问题时遇到困难,是因为第一个问题涉及的变量,但现在我因为生病和缺乏睡眠而感到迷糊。如果有人能像对五岁小孩一样解释给我听,如何将相同的输出写入控制台和日志文件,我将非常感激。

非常感谢。

1 个回答

2

你的代码正在设置一个名为 'myproject' 的日志记录器:

logger = logging.getLogger('myproject')
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

如果你在这个日志记录器上使用方法,所有功能都会正常工作:

logger.info('foo bar')
logging.getLogger('myproject').info('foo bar')

但是如果你只是使用模块级别的函数,那就不行:

logging.info('foo bar')

为什么呢?因为模块级别的函数使用的是默认的根日志记录器,而不是你配置的那个。想了解更多,可以查看文档

通常,你可以通过为每个模块创建一个模块级别的 logger 对象来解决这个问题,像这样:

logger = logging.getLogger(__name__)

…或者创建一个类或实例属性 logger,像这样:

self.logger = logging.getLogger('{}.{}'.format(__name__, cls.__name__))

然后通过这个 loggerself.logger 对象来完成所有操作,而不是通过模块级别的函数。

那么,模块级别的函数为什么还存在呢?主要是为了方便在简单程序中使用。如果这对你来说合适,并且你想使用它们,可以这样做;你只需要配置根日志记录器,而不是其他的。把第一行改成这样:

logger = logging.getLogger()

现在当你配置 logger 时,你也在配置模块级别的函数。

撰写回答