百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

python日志输出你会想到啥?不妨来看看这几个模块的用法

off999 2024-10-07 12:17 32 浏览 0 评论

日志可以说是每个开发人员必备的功能 ,通过它可以方便的帮我们找出程序中的一些错误 ,因此要使用到一个好的日志模块或方法对我们来说,也是比较重要的 。接下来我们就介绍python中支持输出日志的4个方法或模块,它们分别是:

  • print()
  • pprint()
  • logging
  • loguru


1.print()

print是一个内置函数,可以直接调用,也是在写代码时最常用的打印函数 。我们最常用的就是输入一个变量,然后进行打印,其实在print中有如下参数:

  • sep : 在值之间插入字符串,默认为空格。
  • end : 在最后一个值之后附加的字符串,默认为换行符
  • flush: 是否强制刷新,这个参数一般和file一起使用 。
  • file : 输出到文件

代码示例:

以下对print中不同的参数进行代码示例

将print语句的输出信息写入到文件中 。需要注意的是:若输出到文件时,不加flush 或者flush=False时,默认先将print输出信息写入内存中,当文件关闭时才把文件进行输出 ;但是当flush=True时,每次print的信息都会直接写入到文件中 。

2.pprint()

pprint()方法能够打印python的各种数据结构,使用这个方法可以将数据结构美化,从而在看起来更加方便 。

pprint()方法是包含在pprint模块中的,在pprint模块中还有好几个方法,这里我们只介绍pprint()方法

若要使用pprint,需要先进行安装 。

安装命令:

pip install pprint

接下来,我们需要导入pprint(),

导入命令:

from pprint import pprint

pprint方法中也可以传入多个参数 ,具体如下:

命令说明:

pprint(object, stream=None, indent=1, width=80, depth=None, *,compact=False)
  • object :具体的数据
  • stream:输出文件流,若不填写,默认为控制台
  • indent: 数据进行换行时的缩进
  • width : 每一行数据的默认宽度(长度),超过后换行
  • depth: 要展示数据结构的深度,超过深度会以...代替


示例代码:

1.通过width和indent可以控制数据的每行宽度和每行开头的缩进

2.通过depth可以控制数据结构的层级,多于参数中的值,数据结构会被...代替。

3.将数据输出到文件中

3.logging模块

logging是python内置的一个日志模块,它可以将日志分为不同的级别,按不同级别的日志进行输出 ;其次它还可以对日志进行格式化,对输出的信息显示更加美观 ; 同时也支持将日志输出到不同地方,如控制台或文件中 。

在logging中提供了很多的函数和类,以满足日志输出的不同需求,以下表格记录了logging模块中主要的函数,类或者常量 。

3.1 输出不同级别日志

通过上图我们可以看到,无论何种实现方式,只是将warning级别及以上日志输出,但是并没有讲debug和info日志输出 。这是什么原因导致的呢 ?

其实答案就是在logging模块内,它会设置一个默认的日志级别,当我们调用不同的日志方法时,其内部要进行一步和默认的日志进行比较,若小于设置的日志级别,则不会往出输出 。而默认的日志级别就是WARNING。以下为logging模块内部源代码设置,经实测,修改此默认设置会改变日志输出 。

root = RootLogger(WARNING)
Logger.root = root
Logger.manager = Manager(Logger.root)

3.2 基本配置方法basicConfig()

在上一个部分我们看到,每条日志的输出格式为:

WARNING:root:这是一条warning日志
ERROR:root:这是一条error日志

总结起来就是: 日志级别:日志名称:日志内容 ,但是这样的日志格式太过简陋,不能很好帮我们定位程序中出现的问题 。那如果我们想自定义日志的输出格式怎么办呢 ? 其中方法之一就是使用basicConfig() .

首先我们来看下,basicConfig都有哪些参数 ?

配置日志信息,将日志写入到文件中 :

配置日志级别和格式:

通过level可以设置日志级别,可以通过format可以自定义日志格式 ,具体如下:

最后需要说明的是,通过basicConfig配置后的对象是一个单例,只要进行了自定义配置,后续再使用logging就都会按照自定义的配置执行了 。


3.3 日志处理器:Handler

Handler的作用是将日志分发到handler指定的位置,如控制台、文件、网络、邮件等。但是需要注意的是,Handler是一个父类,在Handler类中并没有去实现如上面描述的功能(输出到文件,控制台等),真正完成这些功能的是Handler的子类。所以,我们要使用Handler的功能,一般都是直接调用Handler的子类 ,具体包含的子类有:

但是在Handler这个类中,有两个常用的方法 ,无论使用哪个子类,基本都会使用到这两个方法 。

3.4 日志格式化器:Formatter

Formater对象用于配置日志信息的顺序、结构和内容。虽然这个类的构造方法中有三个参数,但是有只有一个是常用到的,也就是要输出日志的格式内容 。

比如我要自定义的日志格式为:

import logging

#自定义日志格式
fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'
formatter = logging.Formatter(fmt)

若想要按照如上格式输出,还需要将创建的formatter加入到日志处理器中 。所以,以上代码还需完善,具体如下:

import logging 

# 创建控制台处理器
sh = logging.StreamHandler()

#自定义日志格式
fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'
formatter = logging.Formatter(fmt)

# 将日志格式化器加入到处理器
sh.setFormatter(formatter)

但是即便这样,还是无法按照自定义格式输出 ,这是因为我们还需要将处理器最终加入到日志器中 。那么接下来我们就来了解下日志器 。

3.5 日志器:Logger

日志器的主要作用是配置日志级别和接收日志处理器中的对象,以确定最终将日志要输出到哪 ?所以我们要先初始化一个Logger的对象 。

logger  = logging.Logger('test',level=logging.DEBUG)

在初始化logger对象时,需要在Logger中传递两个参数,第一个是日志名称,第二个是日志级别 。如上所示 。

初始化日志对象后,即可通过Logger中的addHandler()方法来添加日志处理器了 ,具体如下:

需要注意的是,以上申明日志器对象时,必须要传入一个日志名称,而这个名称,有时候并非是一个重要选项 ,可能我们也不关注这个日志名称是什么? 那么我们可否不传递这个日志名称而直接获得一个Logger对象呢 ? 答案是可以的 ,但是需要调用一个方法,即getLogger()。也就是说上面的初始化logger对象代码可以修改为如下:

import logging
logger = logging.getLogger()

那么,通过如上申明logger也能正常使用,这时如果传递了日志name,则日志名字就会按照传递后的名字显示,若没有传递,则默认为root .

3.6 日志过滤器:Filter

Filter可以被Logger用来做更细粒度的、更复杂的过滤功能。它只允许某个logger层级下的日志事件通过过滤。该类定义如下:

class logging.Filter(name='')
    filter(record)

比如,一个filter实例化时传递的name参数值为'A.B',那么该filter实例将只允许名称为类似如下规则的loggers产生的日志记录通过过滤:'A.B','A.B,C','A.B.C.D','A.B.D',而名称为'A.BB', 'B.A.B'的loggers产生的日志则会被过滤掉。如果name的值为空字符串,则允许所有的日志事件通过过滤器。


3.7 实现自定义日志器的流程

当需要在程序中封装自己的日志处理器的话,我们就会用到了处理器(Handler),格式化器(Formatter)及日志器(Logger)了,而使用他们的基本流程也都是如下所示 :

以下为代码示例

def log_config():
    #创建日志器
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    #创建控制台输出器
    sh = logging.StreamHandler()
    #创建文件输出器
    log_dir = Path(BASE_DIR + '/log')
    if not log_dir.is_dir():
        os.mkdir(log_dir)
    log_file = os.path.join(log_dir,'ihrm.log')
    th = logging.handlers.TimedRotatingFileHandler(log_file,when='midnight',interval=1,backupCount=7,encoding='utf-8')
    #创建格式化器
    fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'
    formatter = logging.Formatter(fmt)
    #把格式化器加入输出器
    sh.setFormatter(formatter)
    th.setFormatter(formatter)
    #把处理器加入日志器
    logger.addHandler(sh)
    logger.addHandler(th)


4.loguru模块

和logging一样,loguru也是一个日志库,所不同的是,这个第三方库基本不需要做任何配置就可以直接使用,而且很重要的一点是使用的logger对象无需创建,直接导入的logger对象也是单例模式,直接使用即可。要想使用它需要先安装。

安装命令:

pip install loguru

导入

from loguru import logger


4.1 输出不同级别的日志

从以上可以看到,我们直接导入的logger其实就是一个对象 ,通过该对象可以直接调用不同级别的日志方法 。另外,我们也注意到,该日志输出后还是带不同颜色的 ,而且默认输出日志格式就很清晰,比较容易定位问题 。


4.2 输出到文件:add方法

很多情况下,我们会将日志输出到文件 ,那么对于loguru输出到文件的配置也有非常强大的支持 ,比如格式按级别输出,输出多个文件,文件自动分隔等等 。那么这些功能的支持其实就需要一个方法就可以搞定,也就是add方法 。

常用参数

可以看到,add方法中其实有很多参数 ,那么接下来我们先了解几个常用的参数 。

  • sys.stderr : 输出文件
  • format :设置格式化
  • filter : 过滤器
  • level :设置级别

日志分隔

如果想对日志进行分隔,比如按文件大小分隔,或者定时分隔,在add方法中,只需要一个参数即可搞定 。这个参数就是rotation,具体代码如下:

logger.add("file_1.log", rotation="500 MB")    # 每隔500M重新生成一个新文件
logger.add("file_2.log", rotation="12:00")     # 每天12点生成一个新文件
logger.add("file_3.log", rotation="1 week")    # 每隔一周生成一个新文件

logger.add("file_X.log", retention="10 days")  # 每隔10天生成一个新文件

logger.add("file_Y.log", compression="zip")    # 文件写入后同时压缩该文件为zip格式

4.3 日志格式化

除了以上功能外,输出的日志可以像format方法一样,可以对日志进行格式化 。

4.4 记录崩溃日志

在很多情况下,在代码运行出错的地方没有配置日志 ,我们就没法追踪错误所在了 。但是使用loguru的装饰器,我们就可以直接进行 跟着错误日志了 的记录了,类似这样的配置即可:

from loguru import logger

@logger.catch
def my_function(x, y, z):
    # An error? It's caught anyway!
    return 1 / (x + y + z)

my_function(0,0,0)

可以看出,当程序报错时,我们可以很清晰的看到错误的代码以及报错后各种输出信息 。

5.总结

最后,我们将上面的4个方法或模块放在一起做一个对比,以确定它们各自的优缺点 。

从上图基本可以看出 ,它们都各有优势 , 我们不好说那个是最好的,但都有各自的使用场景 。

  • print : 更加使用程序快速打印,不在乎日志格式,只想更快看到结果 ,一般用于程序的某个片段或者单点进行调试输出 。
  • pprint: 对元组,列表,字典数据打印更加直观友好,若输出的是这种格式,可以优先考虑pprint .
  • logging :对实现一个系统或框架时比较合适 ,而且对日志需求有更高要求,可以优先考虑logging
  • loguru :对实现一个系统或框架也比较合适 ,但是更加轻量化,不需要配置 ,若对日志需求要求不高,可优先考虑loguru

相关推荐

win10win7双系统引导设置(win10 win7双系统引导)

 步骤如下:  1、首先我是开机时按F8,进入安全模式界面。但是进去的时候等待了几分钟都无反应,上面一直显示请稍等。  2、没办法只有按下复位键重启电脑,因电脑之前装有一键GHOST备份,于是果断还原...

ie缓存清理在哪里(ie缓存如何清除)

?  1、首先打开IE浏览器,选择IE浏览器的工具这一选项;  2、下一步选择工具中的Internet的选项;  3、下一步就是在Internet选项中的常规的选项中;  4、选择常规--浏览历史记录...

华为正版鸿蒙40电脑操作系统下载中文版

安装华为鸿蒙40系统正式版需要先下载官方固件包,然后将固件包放到手机内部存储或外部存储卡中。打开手机设置,选择系统更新,点击“手动更新”,选择已下载的固件包进行安装。安装前请备份重要数据并确保手机电量...

笔记本电脑哪个牌子好用又实惠

1.神舟优雅X4优点:1.35kg很轻巧,14英寸够便携固态硬盘,速度快,有背光键盘。缺点:配置较低,只能轻度办公,售后一般。2.攀升MaxBookP1优点:零噪音,金属机身,固态硬盘,大触摸板,背...

电脑一开机就进入bios界面(电脑开机就会进入bios)

原因一:你的BIOS电池没有电了。解决方式:更换电池即可原因二:没有软驱但启用了软驱解决:可将软驱禁用——开机按DEL进BIOS,选择:STANDARDCMOSFEATURESDRIVEA:...

电脑windows7旗舰版怎么样(电脑windows7旗舰版好不好)

win7旗舰版挺好使的不过现在可以选择更win10。Windows7旗舰版属于微软公司开发的Windows7操作系统系统系列中的功能最高级的版本,也被叫做终结版本,是为了取代WindowsXP...

手机软件怎么升级最新版本呢
  • 手机软件怎么升级最新版本呢
  • 手机软件怎么升级最新版本呢
  • 手机软件怎么升级最新版本呢
  • 手机软件怎么升级最新版本呢
office2010老是弹出安装程序

没看到截图,最好是吧提示信息完整截图发上来。因为信息不会是仅仅“更改安装”几个字的。猜测是已经安装有Office2010了或原本的2010没有卸载干净。

win8玩游戏稳定吗(win8的游戏win10能玩吗)

1、确定驱动是最稳定的公版驱动,新驱动不一定适合游戏不要贸然升级。 2、确定电源已经设置为高性能模式。3、游戏过程开个游戏加加,可以自动为你切换独显,并且自动释放内存。也可以通过它注意下CPU占用,如...

win10系统更新版本(win10系统更新版本能回退吗)

win10怎么更新到1909版本win101909升级方法一:WindowsUpdate更新:1.依次点击开始—设置—更新和安全—windows更新—检查更新,需要更新补丁至最新,如果你经常不更新...

win7升级win10要留多少空间(windows7升级windows10需要多长时间)

win7电脑在系统已经激活并且开启系统更新的情况下,符合条件的系统会在右下角弹出windows10免费升级,直接点击确定就开始升级了。或者下载win10安助手,运行软件后会自动下载windows1...

国外比较开放的浏览器(国外比较开放的浏览器推荐)

1、打开控制面板。2、点击“检查防火墙状态”。3、点击左侧“高级设置”。4、选中“入栈规则”。5、右侧点击“新建规则”。6、选择“端口”。7、选择“TCP”,选中“特定端口”并输入你要开发的端口,或者...

一健ghost下载(一键ghost v2015.07.05)

你的是原版镜像,当然无法识别。。你可以使用微软usb工具。将镜像写入U盘或光盘。

纯净无毒的win7下载(有没有纯净的win7系统)

下面提供的是微软发布的Windows7各版本光盘ISO镜像下载地址,原始文件均来源自MSDN,和零-售彩盒版本光盘内容完全一致。请放心下载。(如果需要光盘的买家,请无视以下内容)下...

ie浏览器文件损坏怎么修复(ie浏览器破坏怎么恢复)

可以在浏览记录里面查到。重新下载一次就行了如果你在IE浏览器里面下载的文件被你不小心删掉了,而且这个文件对你来说很重要,你可以打开你的IE浏览器选择历史记录,在历史记录里面就可以找到相关的下载的地方,...

取消回复欢迎 发表评论: