在上一篇文章《Python系统模块os》中我留了一个问题,就是python中怎么删除非空的目录,这里给出答案。Python删除非空目录使用的是shutil模块。这个模块一般用于复制文件,但是它也具有删除非空目录的能力。我们看一下它是怎么删除的。
>>> os.makedirs('dir1/dir2')
>>> os.listdir('dir1')
['dir2']
>>> shutil.rmtree('dir1')
>>> os.listdir()
[]
在上面的示例代码中,我先创建了一个两级目录 dir1/dir2,我使用shutil.rmtree()函数来删除,可以看到可以直接删除成功。它的用法就是直接给出对应的目录路径就可以了。
今天我要介绍的是python提供的日志记录模块logging,说到日志,相信不管是做开发的同学还是做日志的同学都知道,这个功能是非常重要的。因为从日志里面我们可以追踪整个程序的运行过程,查看报错信息,进行故障分析等等,应用可以说是非常广泛。说到这里,学过Python基础的同学可能会问,Python不是有print函数可以用来输出调试信息吗?
没错,print函数确实可以用来输出,但是在实际的生产环境代码中,日志需要划分对应的级别,根据不同的目的输出不同数量的日志。例如排错的时候,就需要更详细一点的日志,而正常运行的时候,输出少量日志即可。这些功能都是print函数无法满足的,而Python提供的logging库则可以满足需求,话不多说。我们来看这个模块的一些知识。
日志级别
刚我们说到,不同的目的需要不同级别的日志。在logging模块中,将日志划分为7个级别,分别是:
- CRITICAL,灾难级别,对应数值50
- ERROR,错误级别,对应数值40
- WARNING,警告级别,对应数值30(默认值)
- INFO,信息级别,对应数值20
- DEBUG,调试级别,对应数值10
- NOTEST,非测试,对应数值0
当你把日志级别设置为其中一个时,你在程序中进行输出的时候,只有输出位置的信息级别高于默认配置,才运行让你把日志信息输出到文件或者控制台。也就是说,默认值是30,你输出位置的级别是30,40,50,可以输出,20,10,0级别的信息不允许输出。
当你需要进行程序调试的时候,把日志级别改为DEBUG,那么能够输出的日志数值大于10就够了,那么可以输出的信息就更多,有利于调试。
格式化字符串
我们在各个应用程序的日志里看到的信息一般都会有一些标准格式,常见的是:
什么时候(日期 时间) 谁(哪个程序) 做了什么操作 导致了什么后果
而logging模块中,也可以定制这样的日志格式,它是通过不同格式的字符串来实现的,我们看一下常用的字符串有哪些。
- %(message)s,日志的内容,需要用户自己提供信息字符串message
- %(asctime)s,日志的时间,默认格式是YYYY-mm-dd HH:MM:SS,sss,精确到毫秒
- %(funcName)s,日志调用的位置,即日志在哪个函数里被调用。便于排错
- %(levelno)s,日志级别,使用INFO,DEBUG这样的值
- %(lineno)s,日志调用的代码行数,即在哪一行代码处报错,便于排错。
- %(module)s,日志在哪个模块被调用,便于排错
- %(process)d / %(thread)d,进程/线程 ID,即调用日志模块的进程/线程ID。
- %(processName)s / %(threadName)s,进程/ 线程名称,即调用日志模块的进程/线程ID。
基本知识就这些,我们来看一个简单的示例:
import logging
# 格式化字符串
FORMAT = '%(asctime)-15s\t Log out info : %(thread)d %(threadName)s %(message)s'
# 使用格式化字符串来初始化日志模块输出的日志格式
logging.basicConfig(format=FORMAT)
# 输出日志信息
logging.info("This is an info message")
logging.warning("This is a warning message")
代码执行后的输出结果是
2020-02-27 20:40:10,701 Log out info : 140552040826688 MainThread This is an warning message
我们在上面日志级别里说到,WARNING级别是默认级别,而低于这个级别的无法输出。logging也为每个级别提供了对应的函数,例如这里代码中的logging.info和logging.warning,就是用来输出不同级别的日志信息。因此只有logging.warning的信息可以输出,而logging.info级别因为低于WARNING,不允许输出。输出的内容包括我们定义的日期、线程ID,线程名称,自定义的日志信息。
因此,在你的代码中,在异常处理的时候,使用WARNING级别的信息,普通的调试信息则一般建议使用INFO级别来进行输出。
修改日志级别和日期格式
当默认日志级别是WARNING的时候,INFO级别是无法输出的,那么如果我们需要对程序进行调试的时候怎么办呢?当然是修改默认的日志级别了,默认的日志级别可以在日志模块初始化的时候进行设置,格式是:
logging.basicConfig(format=FROMAT, level=logging.INFO)
这样就可以把日志默认级别改为INFO,如果还想输出更多的信息进行调试,可以改为更低的DEBUG级别。但是同时别忘了,在你的程序中,输出的日志定义的格式也需要分级的。
上面格式化字符串中我们看到,默认的日期格式是YYYY-mm-dd HH:MM:SS,sss,而每个开发人员可能习惯不一样,或者说每个公司的标准不一样,这个时候可能就需要修改日期格式了。这个参数的修改也是在日志模块初始化的时候进行,用法是:
logging.basicConfig(format=FORMAT, datefmt='%Y/%m/%d %I:%M:%S')
在上面的示例中,我们将输出的日期改为了上面的格式。这里%Y字样的字符串,是日期格式化的内容,
- %Y表示YYYY
- %m表示mm
- %d表示dd
- %I表示HH格式,但是是12小时,24小时使用%H
- %M表示MM格式分钟
- %S表示SS格式秒
最终的输出结果就是:2020/02/27 08:43:22 Log out info : 140034488715072 MainThread This is an warning message
输出日志到文件
上面的基本配置中,没有配置是否要把日志输出到文件,那么它默认就会把文件输出到控制台。必须指定输出文件的位置,才会自动输出到文件中。配置格式如下:
logging.basicConfig(format=FORMAT, filename='/var/log/demo.log')
这样配置以后,日志就会自动输出到/var/log/demo.log这个文件中,这里有几个需要注意的地方:
- 需要保证程序对这个日志文件有读写权限
- 尽量使用绝对路径,使用相对路径,可能会因为程序执行的位置不同,导致日志文件出现在不同的位置
- 还有一个filemode参数设置日志文件打开方式,默认值是'a',即追加的方式。
以上就是logging模块的基本用法,如果觉得对你有帮助,可以为我点个赞。