一篇文章教你如何用Python记录日志

发表于:2018-3-22 09:36

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:李趴趴要化身女超人    来源:伯乐在线

  对一名开发者来说最糟糕的情况,莫过于要弄清楚一个不熟悉的应用为何不工作。有时候,你甚至不知道系统运行,是否跟原始设计一致。
  在线运行的应用就是黑盒子,需要被跟踪监控。最简单也最重要的方式就是记录日志。记录日志允许我们在开发软件的同时,让程序在系统运行时发出信息,这些信息对于我们和系统管理员来说都是有用的。
  就像为将来的程序员写代码文档一样,我们应该让新软件产生足够的日志供系统的开发者和管理员使用。日志是关于应用运行状态的系统文件的关键部分。给软件加日志产生句时,要向给未来维护系统的开发者和管理员写文档一样。
  一些纯粹主义者认为一个受过训练的开发者使用日志和测试的时候几乎不需要交互调试器。如果我们不能用详细的日志解释开发过程中的应用,那么当代码在线上运行的时候,解释它们会变得更困难。
  这篇文章介绍了 Python 的 logging 模块,包括它的设计以及针对更多复杂案例的适用方法。这篇文章不是写给开发者的文档,它更像是一个指导手册,来说明 Python 的 logging 模板是如何搭建的,并且激发感兴趣的人深入研究。
  为什么使用 logging 模块?
  也许会有开发者会问,为什么不是简单的 print 语句呢? Logging 模块有很多优势,包括:
  1、多线程支持
  2、通过不同级别的日志分类
  3、灵活性和可配置性
  4、将如何记录日志与记录什么内容分离
  最后一点,将我们记录内容从记录方式中真正分离,保证了软件不同部分的合作。举个例子,它允许一个框架或库的开发者增加日志并且让系统管理员或负责运行配置的人员决定稍后应该记录什么。
  Logging 模块中有什么
  Logging 模块完美地将它的每个部分的职责分离(遵循 Apache Log4j API 的方法)。让我们看看一个日志线是如何通过这个模块的代码,并且研究下它的不同部分。
  记录器(Logger)
  记录器是开发者经常交互的对象。那些主要的 API 说明了我们想要记录的内容。
  举个记录器的例子,我们可以分类请求发出一条信息,而不用担心它们是如何从哪里被发出的。
  比如,当我们写下 logger.info(“Stock was sold at %s”, price) 我们在头脑中就有如下模块:
  我们需要一条线。假设有些代码在记录器中运行,让这条线出现在控制台或文件中。但是在内部实际发生了什么呢?
  日志记录
  日志记录是 logging 模块用来满足所有需求信息的包。它们包含了需要记录日志的地方、变化的字符串、参数、请求的信息队列等信息。
  它们都是被记录的对象。每次我们调用记录器时,都会生成这些对象。但这些对象是如何序列化到流中的呢?通过处理器!
  处理器
  处理器将日志记录发送给其他输出终端,他们获取日志记录并用相关函数中处理它们。
  比如,一个文件处理器将会获取一条日志记录,并且把它添加到文件中。
  标准的 logging 模块已经具备了多种内置的处理器,例如:
  多种文件处理器(TimeRotated, SizeRotated, Watched),可以写入文件中
  1、StreamHandler 输出目标流比如 stdout 或 stderr
  2、SMTPHandler 通过 email 发送日志记录
  3、SocketHandler 将日志文件发送到流套接字
  4、SyslogHandler、NTEventHandler、HTTPHandler及MemoryHandler等
  目前我们有个类似于真实情况的模型:
  
  大部分的处理器都在处理字符串(SMTPHandler和FileHandler等)。或许你想知道这些结构化的日志记录是如何转变为易于序列化的字节的。
  格式器
  格式器负责将丰富的元数据日志记录转换为字符串,如果什么都没有提供,将会有个默认的格式器。
  一般的格式器类由 logging 库提供,采用模板和风格作为输入。然后占位符可以在一个 LogRecord 对象中声明所有属性。
  比如:’%(asctime)s %(levelname)s %(name)s: %(message)s’ 将会生成日志类似于 2017-07-19 15:31:13,942 INFO parent.child: Hello EuroPython.
  请注意:属性信息是通过提供的参数对日志的原始模板进行插值的结果。(比如,对于 logger.info(“Hello %s”, “Laszlo”) 这条信息将会是 “Hello Laszlo”)
  所有默认的属性都可以在日志文档中找到。
  好了,现在我们了解了格式器,我们的模型又发生了变化:
 
  过滤器
  我们日志工具的最后一个对象就是过滤器。
  过滤器允许对应该发送的日志记录进行细粒度控制。多种过滤器能同时应用在记录器和处理器中。对于一条发送的日志来说,所有的过滤器都应该通过这条记录。
  用户可以声明他们自己的过滤器作为对象,使用 filter 方法获取日志记录作为输入,反馈 True / False 作为输出。
  出于这种考虑,以下是当前的日志工作流:
  
  记录器层级
  此时,你可能会对大量复杂的内容和巧妙隐藏的模块配置印象深刻,但是还有更需要考虑的:记录器分层。
  我们可以通过 logging.getLogger() 创建一个记录器。这条字符向 getLogger 传递了一个参数,这个参数可以通过使用圆点分隔元素来定义一个层级。
  举个例子,logging.getLogger(“parent.child”) 将会创建一个 “child” 的记录器,它的父级记录器叫做 “parent.” 记录器是被 logging 模块管理的全局对象,所以我们可以方便地在项目中的任何地方检索他们。
  记录器的例子通常也被认为是渠道。层级允许开发者去定义渠道和他们的层级。
  在日志记录被传递到所有记录器内的处理器时,父级处理器将会进行递归处理,直到我们到达顶级的记录器(被定义为一个空字符串),或者有一个记录器设置了 propagate = False。我们可通过更新的图中看出:
 
  请注意父级记录器没有被调用,只有它的处理器被调用。这意味着过滤器和其他在记录器类中的代码不会在父级中被执行。当我们在记录器中增加过滤器时,这通常是个陷阱。
  工作流小结
  我们已经阐明过职责的划分以及我们是如何微调日志过滤。然而还是有两个其他的属性我们没有提及:
  记录器可以是残缺的,从而不允许任何记录从这被发出。
  一个有效的层级可以同时在记录器和处理器中被设置。
  举个例子,当一个记录器被设置为 INFO 的等级,只有 INFO 等级及以上的才会被传递,同样的规则适用于处理器。
  基于以上所有的考虑,最后的日志记录的流程图看起来像这样:
 
  如何使用日志记录模块
  现在我们已经了解了 logging 模块的部分及设计,是时候去了解一个开发者是如何与它交互的了。以下是一个代码例子:
import logging
def sample_function(secret_parameter):
logger = logging.getLogger(__name__)  # __name__=projectA.moduleB
logger.debug("Going to perform magic with '%s'",  secret_parameter)
...
try:
result = do_magic(secret_parameter)
except IndexError:
logger.exception("OMG it happened again, someone please tell Laszlo")
except:
logger.info("Unexpected exception", exc_info=True)
raise
else:
logger.info("Magic with '%s' resulted in '%s'", secret_parameter, result, stack_info=True)
  它用模块 __name__ 创建了一个日志记录器。它会基于项目结构创建渠道和等级,正如 Pyhon 模块用圆点连接一样。
  记录器变量引用记录器的 “module” ,用 “projectA” 作为父级, “root” 作为父级的父级。
  在第五行,我们看到如何执行调用去发送日志。我们可以用 debug 、 info 、error 或 critical 这些方法之一在合适的等级上去记录日志。
  当记录一条信息时,除了模板参数,我们可以通过特殊的含义传递密码参数,最有意思的是 exc_info 和 stack_info。它们将会分别增加关于当前异常和栈帧的信息。为了方便起见,在记录器对象中有一个方法异常,正如这个错误调用 exc_info=True 。
  这些是如何使用记录器模块的基础,但是有些通常被认为是不良操作的做法同样值得说明。

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号