【问题标题】:How to log source file name and line number in Python如何在 Python 中记录源文件名和行号
【发布时间】:2010-10-06 16:35:53
【问题描述】:

是否可以装饰/扩展 python 标准日志记录系统,以便在调用日志记录方法时,它还会记录文件和调用它的行号或调用它的方法?

【问题讨论】:

    标签: python logging


    【解决方案1】:

    当然,请在日志记录文档中查看 formatters。特别是 lineno 和 pathname 变量。

    %(pathname)s 发出日志调用的源文件的完整路径名(如果可用)。

    %(filename)s 路径名的文件名部分。

    %(module)s 模块(文件名的名称部分)。

    %(funcName)s 包含日志调用的函数的名称。

    %(lineno)d 发出记录调用的源行号(如果可用)。

    看起来像这样:

    formatter = logging.Formatter('[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s','%m-%d %H:%M:%S')
    

    【讨论】:

    • 而且,是的,需要考虑变量中的大写/小写混乱
    • 否则称为“非常糟糕的骆驼案例”。
    【解决方案2】:

    Seb's very useful answer 之上,这是一个方便的代码sn-p,它以合理的格式演示了记录器的用法:

    #!/usr/bin/env python
    import logging
    
    logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
        datefmt='%Y-%m-%d:%H:%M:%S',
        level=logging.DEBUG)
    
    logger = logging.getLogger(__name__)
    logger.debug("This is a debug log")
    logger.info("This is an info log")
    logger.critical("This is critical")
    logger.error("An error occurred")
    

    生成此输出:

    2017-06-06:17:07:02,158 DEBUG    [log.py:11] This is a debug log
    2017-06-06:17:07:02,158 INFO     [log.py:12] This is an info log
    2017-06-06:17:07:02,158 CRITICAL [log.py:13] This is critical
    2017-06-06:17:07:02,158 ERROR    [log.py:14] An error occurred
    

    【讨论】:

    • 使用这个获取更多细节: formatter = logging.Formatter( '%(asctime)s, %(levelname)-8s [%(filename)s:%(module)s:%(funcName) s:%(lineno)d] %(message)s')
    • 有没有办法只在代码顶部的一个地方更改日志消息是否打印?我想要两种模式,一种有很多打印,看看程序到底做了什么;一,当它足够稳定时,没有显示输出。
    • @Marie.P.不要在 cmets 中问不同的问题。答案是日志级别。
    【解决方案3】:

    以将调试日志发送到标准输出的方式构建上述内容:

    import logging
    import sys
    
    root = logging.getLogger()
    root.setLevel(logging.DEBUG)
    
    ch = logging.StreamHandler(sys.stdout)
    ch.setLevel(logging.DEBUG)
    FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
    formatter = logging.Formatter(FORMAT)
    ch.setFormatter(formatter)
    root.addHandler(ch)
    
    logging.debug("I am sent to standard out.")
    

    将上述内容放入名为debug_logging_example.py 的文件中会产生输出:

    [debug_logging_example.py:14 -             <module>() ] I am sent to standard out.
    

    那么如果你想关闭日志注释root.setLevel(logging.DEBUG).

    对于单个文件(例如类分配),我发现这是一种比使用 print() 语句更好的方法。它允许您在提交之前在一个地方关闭调试输出。

    【讨论】:

      【解决方案4】:

      对于使用 PyCharm 或 Eclipse pydev 的开发人员,以下将在控制台日志输出中生成日志语句源的链接:

      import logging, sys, os
      logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format='%(message)s | \'%(name)s:%(lineno)s\'')
      log = logging.getLogger(os.path.basename(__file__))
      
      
      log.debug("hello logging linked to source")
      

      请参阅Pydev source file hyperlinks in Eclipse console 了解更多讨论和历史记录。

      【讨论】:

        【解决方案5】:
        # your imports above ...
        
        
        logging.basicConfig(
            format='%(asctime)s,%(msecs)d %(levelname)-8s [%(pathname)s:%(lineno)d in 
            function %(funcName)s] %(message)s',
            datefmt='%Y-%m-%d:%H:%M:%S',
            level=logging.DEBUG
        )
        
        logger = logging.getLogger(__name__)
        
        # your classes and methods below ...
        # An naive Sample of usage:
        try:
            logger.info('Sample of info log')
            # your code here
        except Exception as e:
            logger.error(e)
        

        与其他答案不同,这将记录文件的完整路径和可能发生错误的函数名称。如果您的项目包含多个模块以及分布在这些模块中的多个同名文件,这将非常有用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-04-21
          • 2021-01-29
          • 2011-09-16
          • 2012-06-13
          • 1970-01-01
          • 1970-01-01
          • 2022-01-17
          相关资源
          最近更新 更多