首次使用日志记录模块。我真的有两个问题:
我在创建FileHandler时发现的所有示例都只使用虚拟文件名,但我希望我的日志文件具有某种标题格式。
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
代替log
中的handler = logging.FileHandler(log)
会给我一些关于甚至没有创建的文件的错误。如果没有写入日志文件,我做错了什么?是因为我试图用文件名太聪明了吗?
第二个问题可能以某种方式包含第一个问题。我真正想要的是同时写入控制台和日志文件的方法,因为这个脚本需要很长时间,我想衡量进度。我已经看到有关于如何执行此操作的答案,例如here,但所有这些似乎都假设我想要两个不同输出的不同级别的日志记录;我不。顺便说一句,我确实意识到如果我的脚本没有动态生成日志文件的名称,我可以执行类似python myscript.py | tee log.file
的操作,以避免使用不同的处理程序。
由于第一个问题所涉及的变量,我觉得我无法回答第二个问题,但由于疾病和随后的睡眠不足,我现在很模糊。如果有人能像五十岁那样向我解释如何写入具有相同输出的控制台和日志文件,我将非常感激。
非常感谢。
答案 0 :(得分: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')
为什么呢?因为模块级函数使用默认的根记录器,而不是您配置的根记录器。有关其工作原理的详细信息,请参阅the docs。
通常,处理此问题的方法是为每个模块创建一个模块级logger
对象,如下所示:
logger = logging.getLogger(__name__)
...或类或实例属性logger
,如下所示:
self.logger = logging.getLogger('{}.{}'.format(__name__, cls.__name__))
然后通过logger
或self.logger
对象完成所有操作,而不是通过模块级函数。
那么,为什么模块级功能呢?为了方便简单程序,主要是。如果这听起来适合你,你想使用它们,你可以;您只需配置根记录器而不是其他记录器。将第一行更改为:
logger = logging.getLogger()
现在配置logger
时,您还要配置模块级功能。