为什么Python要以打印日志为荣 , 以单步跟踪为耻?

2012-10-10 00:29:05 +08:00
 sqrabs
对Python八荣八耻中其它那些条都很赞同,唯独对“以打印日志为荣 , 以单步跟踪为耻”不太理解。如果有了问题到处插print能高效debug么?而且Python不是也有Pydb这样的断点调试工具么。。
附八荣八耻:
以动手实践为荣 , 以只看不练为耻;
以打印日志为荣 , 以单步跟踪为耻;
以空格缩进为荣 , 以制表缩进为耻;
以单元测试为荣 , 以人工测试为耻;

以模块复用为荣 , 以复制粘贴为耻;
以多态应用为荣 , 以分支判断为耻;
以Pythonic为荣 , 以冗余拖沓为耻;
以总结分享为荣 , 以跪地求解为耻。
9604 次点击
所在节点    Python
27 条回复
013231
2012-10-10 05:06:39 +08:00
打印日誌查錯效率是O(log n), 單步跟蹤是O(n).
况且單步跟蹤還有很多局限性.
kid7st
2012-10-10 09:03:51 +08:00
@013231 这个效率的说法很有意思,能细说下吗?
局限性在什么地方呢?
rightgenius
2012-10-10 09:09:43 +08:00
顶1l
suckli
2012-10-10 09:19:02 +08:00
@013231 请问这是如何计算出来的?
skyleft
2012-10-10 10:17:45 +08:00
打印日志第n次成功找到bug的概率是1/n,1/(n-1),1/(n-2)...-> 1,把所有期望值求和取平均=
(1+1/2+1/3+...+1/n)/n=1/n在[1,n]上的定积分=ln(n)-ln(1)=ln(n),所以其复杂度为O(ln n)

单步跟踪找到bug的概率期望值为(1+2+3+...+n)/n=(n+1)/2 所以其复杂度为O(n)
skyleft
2012-10-10 10:18:24 +08:00
@suckli 看上面
skydiver
2012-10-10 10:20:00 +08:00
@skyleft 概率算法有问题,打回去重算~
skyleft
2012-10-10 10:26:49 +08:00
@skydiver 第一个不需要除n
cabbala
2012-10-10 10:31:01 +08:00
Python打日志不用print啊,用logger打,而且还能控制打印的粒度。
jianingy
2012-10-10 10:38:24 +08:00
@013231 单步跟踪可以用breakpoints的

一直用print大法调试,现在正努力摆脱中。原因有两个,一个是学了functional programming另一个是看了rob pike的一个建议。把rob pike的帖子贴这里,这才是正确的debug方法,

A year or two after I'd joined the Labs, I was pair programming with Ken Thompson on an on-the-fly compiler for a little interactive graphics language designed by Gerard Holzmann. I was the faster typist, so I was at the keyboard and Ken was standing behind me as we programmed. We were working fast, and things broke, often visibly—it was a graphics language, after all. When something went wrong, I'd reflexively start to dig in to the problem, examining stack traces, sticking in print statements, invoking a debugger, and so on. But Ken would just stand and think, ignoring me and the code we'd just written. After a while I noticed a pattern: Ken would often understand the problem before I would, and would suddenly announce, "I know what's wrong." He was usually correct. I realized that Ken was building a mental model of the code and when something broke it was an error in the model. By thinking about *how* that problem could happen, he'd intuit where the model was wrong or where our code must not be satisfying the model.

Ken taught me that thinking before debugging is extremely important. If you dive into the bug, you tend to fix the local issue in the code, but if you think about the bug first, how the bug came to be, you often find and correct a higher-level problem in the code that will improve the design and prevent further bugs.

I recognize this is largely a matter of style. Some people insist on line-by-line tool-driven debugging for everything. But I now believe that thinking—without looking at the code—is the best debugging tool of all, because it leads to better software.
skydiver
2012-10-10 10:45:17 +08:00
@kid7st
@skyleft 其实简单说就是打印日志可以二分查找,单步只能一步一步跟踪,所以一个是O(log n)一个是O(n)
haohaolee
2012-10-10 10:51:08 +08:00
笑笑就好,有的还不能当真。用调试器又不光是单步,而且用调试器和打印日志也不矛盾
kid7st
2012-10-10 12:06:26 +08:00
@skydiver 二分,这个明白了。thanks!
holmesabc
2012-10-10 12:15:18 +08:00
@haohaolee 同意

就应该说是调试器。
打日志,会直接影响原代码(虽说不会影响逻辑)。

调试器一般那么多功能,运行到指定行,运行到返回什么的
单步的话,我一般是看内存里面变量的值的变化。哪个值不对,在什么地方不对,马上就知道原因。
(当然我说的是java, python还不会用调试器)

如果不是逻辑上的问题,打日志,完全可以。
但是如果是逻辑上的问题,那就蛋疼了。
binux
2012-10-10 12:23:14 +08:00
print一般都会有日志级别,正式发布的时候不会开那么低的,对源代码不会有影响
用print的时候,输出的地方一般都非常关键,而且信息更为实用
调试时,print更容易在非常大段的代码中定位
调试后,print依旧留在代码中,为下次调试带来便利
pengdu
2012-10-10 12:50:48 +08:00
不管是python还是c/c++,都习惯打日志,而不喜欢用单步调试工具。

单步调试工具用起来太蹩脚了,效率低。
clowwindy
2012-10-10 13:01:54 +08:00
本来想说些什么的,但有些东西只有你经历过才能有体会,不经历过说了也不能完全理解,经历过不说也会明白,所有我只能建议楼主,从今天开始,在程序的重要步骤,检测到异常输入的时候,进入了不大可能进入的 else 语句的时候,用 logging 模块打印状态信息,包括现在正准备或者已经做了什么,和关键变量的值。等楼主这么做一段时间之后,自然就明白了。
gonbo
2012-10-10 13:12:31 +08:00
thinking bug -> logging bug -> digging bug
avatasia
2012-10-10 13:39:57 +08:00
原来有明白人知道断点的。

空格缩进这个不能理解, html和代码混杂的project,如果用空格缩进,会相当难受,有时候会非常在意那一点文件传输的体积。
013231
2012-10-10 15:05:56 +08:00
@kid7st 局限性包括:
1. 單步調試會破壞程序的時間特性. 即: 原本併發的操作, 在單步調試時不再併發; 原本在短時間内相繼執行的操作, 單步調試時間隔變長.
2. 對於某些發生頻率非常低的Bug, 恐怕你没有時間開着調試器等到Bug出現.
@jianingy
我們對單步跟蹤的理解有所不同, 在我看來斷點已經不算"單步"跟蹤了.
另外在我看來, 打印日誌更有利於"thinking before debugging" -- 寫一條日誌語句的勞動量遠大於讓調試器跑到下一步或設置一個斷點, 在决定如何寫日誌時, 你不得不仔細思考Bug是如何發生的.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/49591

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX