日志文件是在开发中常见的用于记录程序运行的工具,它就像飞机上的黑盒子,记录下飞行的每时每刻,这样在飞机出现故障的时候,可以很快的找到问题所在。对于应用的开发,Debug和运行来说,日志都相当重要,虽然没有日志程序仍然可以跑,但是对于一个合格的开发者来说,保存日志是一个很良好的习惯。
使用Python的日志模块
在Python中,我们可以使用Python的标准日志模块来写日志,日志模块经过社区开发者的精心设计,用起来很方便,而且使用起来相当灵活,就像这样:
1 | import logging |
在命令行中测试这段代码,会出现:
1 | INFO:root:Hello World |
基本元素说明
- Logger:用于输出的日志的总对象,提供了应用程序可以直接使用的接口
- Handlers:用来指定log的输出方式,将(logger创建的)日志记录发送到合适的输出源
- Formatters:设置日志信息的结构和内容格式,默认的时间格式为%Y-%m-%d %H:%M:%S
- Filter:过滤器,用来过滤的输出内容
Logger
每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,获取Logger的方法:
1 | logger = logging.getLogger(__name__) |
Logger常用函数
Logger.setLevel(level): 指定最低的日志级别,低于lel的级别将被忽略
Logger.addFilter(filt): 添加指定的filter
Logger.removeFilter(filt): 删除指定的filter
Logger.addHandler(hdlr): 增加指定的handler
Logger.removeHandler(hdlr): 删除指定的handler
Logger.log(“debug”,”This is a bug”): 可以通过这个函数直接输出内容并选择对应的告警级别
Logger.DEBUG( ):可以设置的日志级别,Debug可以替换为其他级别
级别
level有以下几个级别
1 | $ python |
优先级从小到大一共分为6级,NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL
如果把Logger的级别设置为DEBUG, 那么小于DEBUG级别的日志将不会输出
Handlers
Handler对象负责发送相关的信息到指定目的地。
Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler( )方法添加多个handler
Handlers常用函数
Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter():给这个handler选择一个格式
Handler.addFilter(filt):新增一个filter对象
Handler.removeFilter(filt):删除一个filter对象
Handlers常用种类
- logging.StreamHandler
– 使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息
– 它的构造函数是:StreamHandler(strm),其中strm参数是一个文件对象,默认是sys.stderr - logging.FileHandler
– 和StreamHandler类似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件
– 它的构造函数是:FileHandler(filename,mode),filename是文件名,必须指定一个文件名。mode是文件的打开方式,默认是’a’,即添加到文件末尾 - logging.handlers.RotatingFileHandler
– 这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建一个新的同名日志文件继续输出。比如日志文件是example.log。当example.log达到指定的大小之后,RotatingFileHandler自动把文件改名为example.log.1。不过,如果example.log.1已经存在,会先把example.log.1重命名为example.log.2。。。最后重新创建 exmaple.log,继续输出日志信息
– 它的构造函数是:RotatingFileHandler( filename, mode, maxBytes, backupCount) 其中filename和mode两个参数和FileHandler一样。maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除
1 | #example |
- logging.handlers.TimedRotatingFileHandler
– 这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间
– 它的构造函数是:TimedRotatingFileHandler( filename ,when ,interval ,backupCount),其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义,interval是时间间隔,when参数是一个字符串,表示时间间隔的单位,不区分大小写。它有以下取值:S 秒 M 分 H 小时 D 天 W 每星期(interval==0时代表星期一)midnight 每天凌晨
1 | #example |
- logging.handlers.SocketHandler
- logging.handlers.DatagramHandler
– 以上两个Handler类似,都是将日志信息发送到网络。不同的是前者使用TCP协议,后者使用UDP协议
– 它们的构造函数是:Handler(host, port),其中host是主机名,port是端口名 - logging.handlers.SysLogHandler
- logging.handlers.NTEventLogHandler
- logging.handlers.SMTPHandler
- logging.handlers.MemoryHandler
- logging.handlers.HTTPHandler
最常用的就是 StreamHandler 和 FileHandler,对于产生Log数量比较大的项目,会使用 RotatingFileHandler 或者 TimedRotatingFileHandler 处理日志文件
Formatters
Formatter对象设置日志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d %H:%M:%S,下面是Formatter常用的一些信息:
参数 | 含义 |
---|---|
%(name)s | Logger的名字 |
%(levelno)s | 数字形式的日志级别 |
%(levelname)s | 文本形式的日志级别 |
%(pathname)s | 调用日志输出函数的模块的完整路径名,可能没有 |
%(filename)s | 调用日志输出函数的模块的文件名 |
%(module)s | 调用日志输出函数的模块名 |
%(funcName)s | 调用日志输出函数的函数名 |
%(lineno)d | 调用日志输出函数的语句所在的代码行 |
%(created)f | 当前时间,用UNIX标准的表示时间的浮 点数表示 |
%(relativeCreated)d | 输出日志信息时的,自Logger创建以 来的毫秒数 |
%(asctime)s | 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896” |
%(thread)d | 线程ID。可能没有 |
%(threadName)s | 线程名。可能没有 |
%(process)d | 进程ID。可能没有 |
%(message)s | 用户输出的消息 |
举个例子
1 | import logging |
1 | cat example.log |