Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中使用根记录器或命名记录器更好吗_Python_Logging - Fatal编程技术网

在Python中使用根记录器或命名记录器更好吗

在Python中使用根记录器或命名记录器更好吗,python,logging,Python,Logging,我试图找出跨多个模块使用python登录的最佳实践。我在这里看到:关于如何使用根记录器跨多个模块进行日志记录。但正如链接所指出的,您无法知道消息在应用程序中来自何处,因为它们都显示名称“root” 在我看来,有两种选择(假设我的模块不在包结构中,而只是同一文件夹中的一组模块): 1) 如示例所示使用根日志记录器,但更改日志格式以包含文件名: # myapp.py import logging import mylib def main(): logging.basicConfig(fo

我试图找出跨多个模块使用python登录的最佳实践。我在这里看到:关于如何使用根记录器跨多个模块进行日志记录。但正如链接所指出的,您无法知道消息在应用程序中来自何处,因为它们都显示名称“root”

在我看来,有两种选择(假设我的模块不在包结构中,而只是同一文件夹中的一组模块):

1) 如示例所示使用根日志记录器,但更改日志格式以包含文件名:

# myapp.py
import logging
import mylib

def main():
    logging.basicConfig(format='%(asctime)s %(filename)s %(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.INFO)  #filename='myapp.log', 
    logging.info('Started')
    mylib.do_something()
    logging.info('Finished')

if __name__ == '__main__':
    main()

#mylib.py
import logging

def do_something():
    logging.info('Do something')




In [4]: import myapp

In [5]: myapp.main()
03/06/2014 12:22:07 PM myapp.py INFO: Started
03/06/2014 12:22:07 PM mylib.py INFO: Do something
03/06/2014 12:22:07 PM myapp.py INFO: Finished
2) 在主应用程序中使用根记录器,但在子模块中使用命名记录器,并在日志格式中使用“名称”而不是“文件名”:

# myapp.py
import logging
import mylib

def main():
    #logging.basicConfig(format='%(asctime)s %(filename)s %(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.INFO)  #filename='myapp.log', 
    logging.basicConfig(format='%(asctime)s %(name)s %(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.INFO)  #filename='myapp.log', 
    logging.info('Started')
    mylib.do_something()
    logging.info('Finished')

if __name__ == '__main__':
    main()

#mylib.py
import logging

def do_something():
    #logging.info('Do something')
    logger = logging.getLogger(__name__)
    logger.info('Do something')



In [3]: import myapp

In [4]: myapp.main()
03/06/2014 12:27:29 PM root INFO: Started
03/06/2014 12:27:29 PM mylib INFO: Do something
03/06/2014 12:27:29 PM root INFO: Finished
Vinay Sajip(日志模块的维护者)制作了一个类似于您的选项#2的日志,只是您可以在任何地方使用命名日志,即使在myapp中:

import logging
import mylib
logger = logging.getLogger(__name__)

def main():
    logging.basicConfig(format='%(asctime)s %(module)s %(levelname)s: %(message)s',
                        datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.INFO)  
    logger.info('Started')
    mylib.do_something()
    logger.info('Finished')

if __name__ == '__main__':
    main()
产生

03/06/2014 12:59:25 PM myapp INFO: Started
03/06/2014 12:59:25 PM mylib INFO: Do something
03/06/2014 12:59:25 PM myapp INFO: Finished
请注意,如果您使用
%(module)s
而不是
%(name)s
,那么您将获得
myapp
,在您获得
root
myapp.py
main\uuuuuu
之前的位置


如果
myapp
有时被称为脚本,有时被导入为模块,那么这种始终使用
logger
的对称性可能特别有用

谢谢!我试过这个,但我不明白为什么。(在myapp和mylib中都有名为“_name_uuu”的记录器。)如果像我的示例中一样导入myapp,则myapp中的_name_uuu就是“myapp”_mylib中的name_uu是“mylib”,所以在每个文件中,当logger=logging.getLogger(name_uu)时,它们不是创建了两个不同的记录器吗?因为每个单独记录器的输出仍被传递到根记录器,然后再传递到控制台,所以它工作吗?另外,如果myapp有时被称为脚本或作为模块导入,您能否详细说明您最后的评论,即始终使用“记录器”是有用的。您的意思是使用logger=logging.getLogger(..)比直接使用root logger更好:logging.info(“..”)?是的,您得到了两个不同的记录器。显示记录器(默认情况下)将记录传播到父记录器。因此根记录器的处理程序有机会处理记录。假设您在主脚本myapp中使用
logging.info
,但在模块中使用
logger.info
。假设稍后您创建了一个新脚本,该脚本导入
myapp
。现在,每当日志消息来自myapp时,日志输出将使用
root
作为
%(name)s
,而为了一致性,您更希望它报告
myapp
。如果您总是使用
logger.info
,即使是在主脚本中,那么您将来也可以证明您的代码不会有一天被用作模块。感谢您的流程图以及您对使用logger的优势的解释。现在我觉得两者都有道理了。不确定我是否应该开始一个新问题,但是:如果在这个例子中我想要有多个处理程序,例如,信息级别转到标准输出和一个文件,错误级别发送到一个电子邮件地址,有没有办法做到这一点?我想它不是logging.addHandler()?可能是logging.config.fileConfig()?