python -- subprocess和logging模块
subprocess模块,相当于调用linux的shell
subprocess模块是对以下两个模块的替换:
- os.system,调用shell命令
- os.spawn,产生一个新进程
logging模块
logging的日志可以分为:
- debug(),默认不打印,级别最低
- info(),默认不打印
- warning()
- error()
- critical(),级别最高
import logging
logging.debug('in the debug')
logging.info('in the info')
logging.warning('in the warning')
logging.error('in the error')
logging.critical('in the critical')
'''
以下是程序的效果(同颜色):
WARNING:root:in the warning
ERROR:root:in the error
CRITICAL:root:in the critical
'''
用logging简单的写日志
import logging
# 加了一句话,屏幕输出没有,log内容去info.log了
logging.basicConfig(filename='info.log', level=logging.DEBUG)
logging.info('in the info')
logging.debug('in the debug')
logging.error('in the error')
logging.warning('in the warning')
logging.critical('in the critical')
'''
当程序执行一次,记录一次log内容,
再执行一遍,会追加上去,并非覆盖。
几个模式
logging.INFO
logging.DEBUG
logging.ERROR
logging.WARNING
logging.CRITICAL
'''
用logging做一些输出的变化
import logging
# 加了一句话,屏幕输出没有,log内容去info.log了,同时加了时间
logging.basicConfig(filename='info.log',
level=logging.DEBUG,
format='%(asctime)s %(message)s',
datefmt='%m/%d/%Y %I:%M:%S %p')
logging.info('in the info')
logging.debug('in the debug')
logging.error('in the error')
logging.warning('in the warning')
logging.critical('in the critical')
# 当程序执行一次,记录一次log内容,
#再执行一遍,会追加上去,并非覆盖。
Python 使用logging模块记录日志涉及四个主要类:
logger提供了应用程序可以直接使用的接口;
每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:
LOG=logging.getLogger(”chat.gui”)
而核心模块可以这样:
LOG=logging.getLogger(”chat.kernel”)- logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。
- logger.addFilter(filt)、logger.removeFilter(filt):添加或删除指定的filter
- logger.addHandler(hdlr)、logger.removeHandler(hdlr):增加或删除指定的handler
- logger.debug()、logger.info()、logger.warning()、logger.error()、logger.critical():可以设置的日志级别
handler将(logger创建的)日志记录发送到合适的目的输出,远程,邮件等等;
handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种handler可以使用。有些handler可以把信息输出到控制台,有些logger可以把信息输出到文件,还有些 handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的handler。可以通过addHandler()方法添加多个多handler- handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
- handler.setFormatter():给这个handler选择一个格式
- handler.addFilter(filt)、handler.removeFilter(filt):新增或删除一个filter对象
每个Logger可以附加多个Handler。接下来我们就来介绍一些常用的Handler:
- logging.StreamHandler
使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。它的构造函数是:
StreamHandler([strm])
其中strm参数是一个文件对象。默认是sys.stderr logging.FileHandler
和StreamHandler类似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件。它的构造函数是:
FileHandler(filename[,mode])
filename是文件名,必须指定一个文件名。
mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a',即添加到文件末尾。logging.handlers.RotatingFileHandler
这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建 一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。它的构造函数是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode两个参数和FileHandler一样。
maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。
backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。- logging.handlers.TimedRotatingFileHandler
这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。
interval是时间间隔。
when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值:- S 秒
- M 分
- H 小时
- D 天
- W 每星期(interval==0时代表星期一)
- midnight 每天凌晨
- filter提供了细度设备来决定输出哪条日志记录,包含哪些字段;
- formatter决定日志记录的最终输出格式。
用logging多方位的输出
import logging
# 创建一个logger
logger = logging.getLogger('TEST-LOG')
logger.setLevel(logging.DEBUG)
# 设置一个屏幕输出的logger, logging.StreamHander(),级别=Warning
sh = logging.StreamHandler()
sh.setLevel(logging.WARNING)
# 设置一个文件输出的logger, logging.FileHander(),级别=Error
# 如果文件名带中文,就要加encoding了
fh = logging.FileHandler("access.log", encoding='utf-8')
fh.setLevel(logging.ERROR)
# 为logger设置一个格式,并赋予他们
sh.formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
sh.setFormatter(sh.formatter)
fh.setFormatter(fh.formatter)
# 添加两个handler到logger
logger.addHandler(fh)
logger.addHandler(sh)
logger.debug('in the debug')
logger.info('in the info')
logger.warning('in the warning')
logger.error('in the error')
logger.critical('in the critical')
logging.handlers.RotatingFileHandler
import logging
from logging import handlers
logger = logging.getLogger('TEST')
# 生成一个log文件,叫timelog.log
log_file = "timelog.log"
# 文件名是log_file的变量,最大10字节,最多备份3个,编码为utf-8
fh = handlers.RotatingFileHandler(filename=log_file, maxBytes=10, backupCount=3, encoding='utf-8')
# 创建formatter
formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s')
# 将formatter赋值给fh
fh.setFormatter(formatter)
# 将fh赋值给logger
logger.addHandler(fh)
logger.warning("test - 1")
logger.warning("test1 - 2")
logger.warning("test1 - 3")
logger.warning("test1 - 4")
logger.warning("test1 - 5")
logger.warning("test1 - 6")
logger.warning("test1 - 7")
logging.handlers.TimedRotatingFileHandler
import logging, time
from logging import handlers
logger = logging.getLogger('TEST')
# 生成一个log文件,叫timelog.log
log_file = "timelog.log"
# 文件名是log_file的变量,5秒一截断,最多备份3个,编码为utf-8
# handlers.TimedRotatingFileHandler会将截断的文件按照截断时间再命名一个文件
fh = handlers.TimedRotatingFileHandler(filename=log_file, when="S", interval=5, backupCount=3, encoding='utf-8')
# 创建formatter
formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s')
# 将formatter赋值给fh
fh.setFormatter(formatter)
# 将fh赋值给logger
logger.addHandler(fh)
logger.warning("test - 1")
time.sleep(4)
logger.warning("test1 - 2")
time.sleep(4)
logger.warning("test1 - 3")
写在后面
Level | When it’s used |
---|---|
DEBUG | Detailed information, typically of interest only when diagnosing problems. |
INFO | Confirmation that things are working as expected. |
WARNING | An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected. |
ERROR | Due to a more serious problem, the software has not been able to perform some function. |
CRITICAL | A serious error, indicating that the program itself may be unable to continue running. |
logging.basicConfig() | format=日志格式 |
---|---|
%(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 | 用户输出的消息 |
graph LR
A["开始"]-->|"logging.getLogger('name')"|B["logger"]
B-->|"logger.addHandler()"|C["fh"]
B-->|"logger.addHandler()"|D["sh"]
C-->|"fh.setFormatter('format')"|E["formatter"]
D-->|"sh.setFormatter('format')"|F["formatter"]