python log日志打印两遍_打印日志 (log) 是比单步跟踪 (debugger) 更好的 Python 排错手段吗?...

本文探讨了在Python编程中,日志与单步调试器各自的优势。虽然单步调试器在查看程序内部状态和复杂逻辑时非常有用,但在某些场景如远程环境、网络应用、并发问题中,日志更具优势。Python的日志调试功能强大,如repr、vars等方法便于打印复杂对象。然而,过多的日志和难以有效监控的对象依然是挑战。在面对更复杂问题时,开发者可能会寻求监控系统或定制调试工具等解决方案。
摘要由CSDN通过智能技术生成

这个问题应该让我回答一下,我调试中使用最多的也是打印日志,这不代表日志就比调试器好用,实际上如果真的可以用单步调试复现问题的话,没有比单步调试更好的debug方法了!

单步调试最重要的作用不是让你看清程序逻辑,如果你看源代码还不清楚这个地方应该是怎样的逻辑的话,那属于基本功的问题。单步调试最大的好处是可以在断点的地方查看所有的内部状态,从而在很复杂的逻辑中,找到引发问题的条件语句。想像一下一个非常复杂的逻辑,涉及到一个100*100的数组,你可以在每次循环的时候用调试器查看数组内部的值,但如果要每个循环都把整个数组打印到日志里,那就太难看清楚了。更何况如果这样的数组还有非常多个,不清楚哪一个出了问题,那就更需要调试器帮助了。

所以如果你的模块在某个单元测试上fail了,显然单步跟踪进去是发现问题的最简单的方法。

=============================分割==================================

调试器这么好为什么我们还需要日志呢?问题在于,单步调试的限制条件太多了:

要么本地执行,要么附加远程调试器而且网络通,这个第一个条件就阻挡住很多情况了,很多bug是跟运行数据相关的,这些bug很可能就只能在部署了软件的那一个环境里能复现,别的环境里运行数据不同就复现不了了,你能在生产环境里打开调试日志,但你能在生产环境里挂调试器吗……

很多问题无法单步调试,或者单步调试的时候不复现,最典型的就是网络相关的应用,你进到单步里面,远端服务就超时了,逻辑都不一样了。还有并发性的问题,只有两个过程同时执行的时候才会死锁,你单步进去,根本遇不到死锁的情况。

根本不知道应该在哪里设断点,通常也是多线程当中的情况,一个线程被一个信号量阻塞了,根本不知道这时候用这个信号量的是哪个线程,怎么设断点……

而相比起来日志在这种时候就有很多优势了:不受环境限制,最多就是重新部署一个带调试日志的版本

基本不会影响运行逻辑,真实运行情况是怎样,打出的就是怎样的日志

可以在所有怀疑的地方同时打上日志,逐个排除

所以可以明白我们选择使用调试日志并不是因为它多么好,而是因为它的不可替代性。从这个角度来说,用日志调试的鄙视单步调试的也情有可原:现在还觉得单步调试有用的,说明根本没有进入到网络编程和大规模并行的领域,大概还停留在写简单单线程逻辑都写不对的水平。但是吧,这个并不是个充要条件,牛人会选择用调试日志,但是用调试日志的不一定都是牛人,所以下次因为这个被鄙视的时候,你可以用这句话喷他一脸。

尤其对于Python来说,Python大部分情况下部署的代码都是源代码,即便在生产环境中也可以即时修改即时生效,有怀疑的地方可以马上修改源码,增加调试日志,然后观察输出,如果没有得到想要的结果,还可以立即当场继续修改。而且Python可以用repr、vars、locals等方法很方便地打印出复杂对象和对象的内部状态,还有很完善的记录异常堆栈的功能(exc_info = True)。这样对于Python,日志调试就更合适了。

=============================分割==================================

实际上调试日志用得越多也就越会觉得调试日志也有很明显的局限性:打印得太多!看不过来!

有的时候不清楚究竟什么原因导致了问题出现,也不知道该打什么日志

有些时候需要监控的对象不能有效地打印出来,比如说需要观察一个对象的属性的变化,然而这个对象的属性太多了,可能还有内部级联的对象,全部打印出来需要写很多代码。还有些对象表现为一个数据结构,比如说链表,比如说树、图,很难有效地打印出来。

有时候bug自然触发的概率很低,需要用一些人为的手段来帮助触发(比如故意在某个原本比较快的过程中增加sleep,模拟压力大时延迟增加的现象),需要增加一些额外的代码。

调试日志也不是终极的解决方案,它还差得远,当你需要解决更加复杂的问题的时候,你会开始发明一些新的调试方式,比如说使用监控系统提交监控数据,比如说交互式的Admin Console。

在现在正在做的项目里,我就增加了一个专门用来调试的Console模块,它是一个可以动态挂载的调试器,挂载上去之后,会在一个独立的线程里启动一个Python Interactive Console,这个Console中挂载了一些额外的函数,可以用来介入到主线程的执行当中,比如说可以查看主线程对象当前的属性值,比如说可以往主线程的事件上挂载一个新的Callback,比如说可以主动调用主线程其他模块的接口,甚至可以通过挂载的Callback中断主线程、进入pdb等等。对调试许多复杂的模块发挥了巨大的作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值