日志模块未写入文件

21

我正在使用logging模块,并传入与其他当前工作的作业相同的参数:

import logging
from inst_config import config3

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] - %(message)s',
    filename=config3.GET_LOGFILE(config3.REQUESTS_USAGE_LOGFILE))
logging.warning('This should go in the file.')

if __name__ == '__main__':
    logging.info('Starting unload.')

使用此方法创建文件名:

REQUESTS_USAGE_LOGFILE = r'C:\RunLogs\Requests_Usage\requests_usage_runlog_{}.txt'.format(
        CUR_MONTH)
def GET_LOGFILE(logfile):
    """Truncates file and returns."""
    with open(logfile, 'w'):
        pass
    return logfile

然而当我运行它时,它会创建文件,但仍将日志信息输出到控制台。我是在Powershell中运行的。

刚试过像这样将其放入主语句:

if __name__ == '__main__':
    logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] - %(message)s',
    filename=config3.GET_LOGFILE(config3.REQUESTS_USAGE_LOGFILE))

    logging.warning('This should go in the file.')

仍然没有运气。


你能展示一下你用来写入日志文件的代码吗? - dot.Py
1
if __name__ == '__main__':运行之前,您是否已经创建了日志文件?我的意思是...如果您运行程序,它会知道日志文件在哪里吗?您可以通过将logging.basicConfig()和在if __name__ == '__main__':块内创建日志文件来进行测试吗? - dot.Py
1
当然,我会尝试一下。编辑:我将其放在主语句中,但仍然打印到控制台:/ - flybonzai
5个回答

34

logging.basicConfig()之前,我添加了以下行,这对我起作用了。

for handler in logging.root.handlers[:]:
    logging.root.removeHandler(handler)

1
@yue dong - 你能解释一下为什么这个方法解决了问题吗?(顺便说一句,它也解决了我的问题)? - Guy Avraham
@yue dong,我是第二个。你能解释一下为什么从根记录器中删除处理程序有帮助吗? - wl2776
它能工作,但里面有什么黑魔法? - Joel Carneiro
谢谢,但这种行为更像是日志记录模块的错误,而不是其他什么? - Sriram
这对我没有起作用,反而破坏了我的代码 :/ - Mr Pablo
我有一个程序经常因为C++外部库而崩溃,我需要解决这个问题。我怀疑当代码不能干净地退出或出现常规的Python错误时,需要进行一些操作。 - Clumsy cat

10

您可以尝试在主文件中运行此代码片段。

import logging 
logging.basicConfig(
    level=logging.INFO, 
    format='%(asctime)s [%(levelname)s] - %(message)s',
    filename='filename.txt')  # pass explicit filename here 
logger = logging.get_logger()  # get the root logger
logger.warning('This should go in the file.')
print logger.handlers   # you should have one FileHandler object

1
我没有包含我的导入,但它确实在文件顶部加载。我已经将我的导入添加到了原始帖子中。 - flybonzai
还是不行。因为它从来没有写入文件,所以也没能创建它。问题可能是 PowerShell 吗?奇怪的是,我有其他配置完全相同的作业,运行得毫无问题。 - flybonzai
1
你在这里说“它没有创建文件”,但在主贴中你说“然而,当我运行它时,它正在创建文件”。那到底是哪个? - John Gordon
这让我找到了解决方案@Forge,出于某种原因,它这次默认使用了一个流处理程序,所以我添加了一个fileHandler - flybonzai

3
除了Forge的回答使用logging.basicConfig()之外,从Python 3.8开始添加了一个参数到basicConfig()中。引用文档:quote the docs
"""
This function does nothing if the root logger already has handlers 
configured, unless the keyword argument *force* is set to ``True``.
...
force     If this keyword  is specified as true, any existing handlers
          attached to the root logger are removed and closed, before
          carrying out the configuration as specified by the other
          arguments.
"""

这就是为什么岳东的移除所有处理程序的答案对某些人有效,以及亚历山大的将logger.handlers重置为[]的答案也有效。
调试logger.handlers(正如Forge的答案所建议的那样)让我看到了一个单独的StreamHandler(因此,除非我使用force=True作为参数,否则basicConfig()对我无效)。
希望这能够在这里的其他所有答案中有所帮助!

2
如果您正在使用默认名称为“”的“root”记录器,则可以尝试以下方法:
logging.getLogger().setLevel(logging.INFO)    
logger = logging.getLogger('')
logger.handlers = []

此外,您可能希望像上面的代码一样指定日志记录级别,这个级别将持续存在于所有后代记录器中。
如果您指定了特定的记录器,则执行以下操作:
logger = logging.getLogger('my_service')
logger.handlers = []
fh = logging.FileHandler(log_path)
fh.setLevel(logging.INFO)
# create console handler
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
logger.addHandler(fh)
logger.addHandler(ch)
logger.info('service started')

上述代码将创建新的记录器"my_service"。如果记录器已经被创建,则清除所有句柄。然后它添加用于写入指定文件和控制台的句柄。也可以查看官方文档
您还可以使用分层记录器。这是直接完成的。
logger = logging.getLogger('my_service.update')
logger.info('updated successfully')

0
import logging

logging.basicConfig(filename="logs.log", filemode="w", format="%(asctime)s %(message)s", level=0, force=True)

for i in range(2):
    print(f"hello {i}")
    logging.info(f"hello {i}")

设置 level=0,filemode="a" 或 "w"。如果你设置 filemode 为 w,它将覆盖之前的日志,但如果你想要追加日志,必须使用 filemode="a"。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接