python日志记录确保仅添加一次处理程序

如何解决python日志记录确保仅添加一次处理程序

| 我有一段代码正在初始化记录器,如下所示。
logger = logging.getLogger()
hdlr = logging.FileHandler(\'logfile.log\')
formatter = logging.Formatter(\'%(asctime)s %(levelname)s %(message)s\')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr) 
logger.setLevel(logging.DEBUG)
不幸的是,该代码被多次调用,有什么方法可以检查该处理程序是否已经存在-我更愿意在不必使用Singleton的情况下实现该代码。 编辑:对不起,忘了提到这是在python 2.5上-干杯,理查德     

解决方法

        作为@offbyone注释,可以将冗余处理程序添加到记录器的同一实例。 用于记录的python文档说-   \“多次调用具有相同名称的getLogger()将返回一个   引用相同的记录器对象。\“ 因此,我们不必担心将实现变成单一实例。 不幸的是,对于与记录器的相同实例相关联的处理程序,情况并非如此。可以附加重复的处理程序。 例- 复制此代码并将其保存在main.py中
import logging
print \'inside main.py\',print \'-\'*50
def logger():

      print \'initializing logger....\'
      logPath = \'.\'
      fileName = \'temp\'

      # configure log formatter
      logFormatter = logging.Formatter(\"%(asctime)s [%(filename)s] [%(funcName)s] [%(levelname)s] [%(lineno)d] %(message)s\")

      # configure file handler
      fileHandler = logging.FileHandler(\"{0}/{1}.log\".format(logPath,fileName))
      fileHandler.setFormatter(logFormatter)

      # configure stream handler
      consoleHandler = logging.StreamHandler()
      consoleHandler.setFormatter(logFormatter)

      # get the logger instance
      logger = logging.getLogger(__name__)

      # set the logging level
      logger.setLevel(logging.DEBUG)

      print \'adding handlers- \'

      #if not len(logger.handlers):
      logger.addHandler(fileHandler)
      logger.addHandler(consoleHandler)

      print \'logger initialized....\\n\'
      print \'associated handlers - \',len(logger.handlers)
      for handler in logger.handlers:
            print handler
      print
      return logger

main_logger = logger()
main_logger.info(\'utilizing main.py logger.\')
print \'exiting main.py\',print \'-\'*50
以及sub.py中的以下代码
print \'inside sub.py\',print \'-\'*50
print \'importing main.py\'
import main
print \'imported main.py\'
import logging
print \'getting logger instance in sub\'
sub_logger = main.logger()
print \'got logger instance in sub\'
sub_logger.info(\"utilizing sub_logger\")
print \'exiting sub.py\',print \'-\'*50
运行sub.py
narayan@y510p:~/code/so$ python sub.py
inside sub.py --------------------------------------------------
importing main.py
inside main.py --------------------------------------------------
initializing logger....
adding handlers- 
logger initialized....

associated handlers -  2
<logging.FileHandler object at 0x7f7158740c90>
<logging.StreamHandler object at 0x7f7158710b10>

2015-08-04 07:41:01,824 [main.py] [<module>] [INFO] [41] utilizing main.py logger.
exiting main.py --------------------------------------------------
imported main.py
getting logger instance in sub
initializing logger....
adding handlers- 
logger initialized....

associated handlers -  4 # <===== 4 handlers (duplicates added)
<logging.FileHandler object at 0x7f7158740c90>
<logging.StreamHandler object at 0x7f7158710b10>
<logging.FileHandler object at 0x7f7158710bd0>
<logging.StreamHandler object at 0x7f7158710c10>

got logger instance in sub
2015-08-04 07:41:01,824 [sub.py] [<module>] [INFO] [10] utilizing sub_logger
2015-08-04 07:41:01,824 [sub.py] [<module>] [INFO] [10] utilizing sub_logger
exiting sub.py --------------------------------------------------
因此,对返回相同记录器的方法的多次调用增加了重复的处理程序。 现在,对于您的问题-   有什么办法可以检查处理程序是否已经存在 就在这里-
logger.handlers
返回与给定的
logger
相关的所有处理程序的列表。 在将处理程序添加到记录器实例之前,请确保不要添加重复的处理程序     在main.py中,只需取消注释表示
if not len(logger.handlers):
的行,并正确缩进以下两行,
if not len(logger.handlers):
    logger.addHandler(fileHandler)
    logger.addHandler(consoleHandler)
现在再次运行sub.py
narayan@y510p:~/code/so$ python sub.py
inside sub.py --------------------------------------------------
importing main.py
inside main.py --------------------------------------------------
initializing logger....
adding handlers- 
logger initialized....

associated handlers -  2
<logging.FileHandler object at 0x7fd67a891c90>
<logging.StreamHandler object at 0x7fd67a862b10>

2015-08-04 08:14:45,620 [main.py] [<module>] [INFO] [41] utilizing main.py logger.
exiting main.py --------------------------------------------------
imported main.py
getting logger instance in sub
initializing logger....
adding handlers- 
logger initialized....

associated handlers -  2 # <===== Still 2 handlers (no duplicates)
<logging.FileHandler object at 0x7fd67a891c90>
<logging.StreamHandler object at 0x7fd67a862b10>

got logger instance in sub
2015-08-04 08:14:45,620 [sub.py] [<module>] [INFO] [10] utilizing sub_logger
exiting sub.py --------------------------------------------------
此外,如果您想限制要添加到logger实例中的处理程序的类型,则可以执行以下操作:
    print \'adding handlers- \'
    # allows to add only one instance of file handler and stream handler
    if len(logger.handlers) > 0:
        print \'making sure we do not add duplicate handlers\'
        for handler in logger.handlers:
              # add the handlers to the logger
              # makes sure no duplicate handlers are added

              if not isinstance(handler,logging.FileHandler) and not isinstance(handler,logging.StreamHandler):
                    logger.addHandler(fileHandler)
                    print \'added file handler\'
                    logger.addHandler(consoleHandler)
                    print \'added stream handler\'
    else:
        logger.addHandler(fileHandler)
        logger.addHandler(consoleHandler)
        print \'added handlers for the first time\'
希望这可以帮助! 编辑:   不幸的是,对于关联的处理程序,情况并非如此   与记录器的相同实例。可以重复   附加的处理程序。 事实证明,上述说法并不完全正确。 假设我们已经在主模块中创建并配置了一个名为\'main_logger \'的记录器(仅配置记录器,不返回任何内容)。
# get the logger instance
logger = logging.getLogger(\"main_logger\")
# configuration follows
...
现在在子模块中,如果我们按照命名层次\'main_logger.sub_module_logger \'创建子记录器,则无需在子模块中对其进行配置。只需按照命名层次创建记录器就足够了。
# get the logger instance
logger = logging.getLogger(\"main_logger.sub_module_logger\")
# no configuration needed
# it inherits the configuration from the parent logger
...
而且它也不会添加重复的处理程序。 参考-在多个模块中使用日志记录     ,        那么logger.addHandler()将不会添加处理程序(如果该处理程序已存在)。要检查处理程序是否已经存在,可以查看logger.handlers列表:
logger = logging.getLogger()
hdlr = logging.FileHandler(\'logfile.log\')
formatter = logging.Formatter(\'%(asctime)s %(levelname)s %(message)s\')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr) 
logger.setLevel(logging.DEBUG)
print logger.handlers
# [<logging.FileHandler object at 0x14542d0>]
logger.addHandler(hdlr)
print logger.handlers
# [<logging.FileHandler object at 0x14542d0>]
此外,如果您有一个或包的
__init__.py
文件,我建议您将此代码放在main()函数中,这样就不必每次都调用它。我还将建议您使用命名记录器,而不要使用根记录器。像这样:
logger = logging.getLogger(__name__)
...
希望这对您有所帮助:)     ,        您也可以只检查处理程序列表是否为空。这是我想到的解决方案:
def setup_logging(self,logfile):
    self._logger = logging.getLogger(\'TestSuite\')
    self._logger.setLevel(logging.INFO)
    host = socket.gethostname().split(\'.\')[0]
    if self._logger.handlers == []:
        fh = logging.handlers.RotatingFileHandler(logfile,maxBytes=10*1024*1024,backupCount=5)
        strfmt = \"%\" + \"(asctime)s [%s] \" % host + \"%\" + \"(message)s\"
        fmt = logging.Formatter(strfmt,datefmt=\"%Y.%m%d %H:%M:%S\")
        fh.setFormatter(fmt)

        self._logger.addHandler(fh)
    self._logger.info(\'-\' * (55 - len(host)))
我看到处理程序已添加多次,因此每个日志消息都多次写入到日志文件中,并且此问题已得到修复。     ,        尝试检查ѭ5是否已设定。例如,如果此代码在函数内部:
logger = None
def init_logger():
    global logger
    if logger is not None:
        #logger has already been initialized
        return
    logger = logging.getLogger()
    hdlr = logging.FileHandler(\'logfile.log\')
    formatter = logging.Formatter(\'%(asctime)s %(levelname)s %(message)s\')
    hdlr.setFormatter(formatter)
    logger.addHandler(hdlr) 
    logger.setLevel(logging.DEBUG)
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res