V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
sqrabs
V2EX  ›  Python

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

  •  1
     
  •   sqrabs ·
    sqrabs · 2012-10-10 00:29:05 +08:00 · 9361 次点击
    这是一个创建于 4221 天前的主题,其中的信息可能已经有所发展或是发生改变。
    对Python八荣八耻中其它那些条都很赞同,唯独对“以打印日志为荣 , 以单步跟踪为耻”不太理解。如果有了问题到处插print能高效debug么?而且Python不是也有Pydb这样的断点调试工具么。。
    附八荣八耻:
    以动手实践为荣 , 以只看不练为耻;
    以打印日志为荣 , 以单步跟踪为耻;
    以空格缩进为荣 , 以制表缩进为耻;
    以单元测试为荣 , 以人工测试为耻;

    以模块复用为荣 , 以复制粘贴为耻;
    以多态应用为荣 , 以分支判断为耻;
    以Pythonic为荣 , 以冗余拖沓为耻;
    以总结分享为荣 , 以跪地求解为耻。
    27 条回复    1970-01-01 08:00:00 +08:00
    013231
        1
    013231  
       2012-10-10 05:06:39 +08:00   ❤️ 1
    打印日誌查錯效率是O(log n), 單步跟蹤是O(n).
    况且單步跟蹤還有很多局限性.
    kid7st
        2
    kid7st  
       2012-10-10 09:03:51 +08:00
    @013231 这个效率的说法很有意思,能细说下吗?
    局限性在什么地方呢?
    rightgenius
        3
    rightgenius  
       2012-10-10 09:09:43 +08:00
    顶1l
    suckli
        4
    suckli  
       2012-10-10 09:19:02 +08:00
    @013231 请问这是如何计算出来的?
    skyleft
        5
    skyleft  
       2012-10-10 10:17:45 +08:00   ❤️ 3
    打印日志第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
        6
    skyleft  
       2012-10-10 10:18:24 +08:00
    @suckli 看上面
    skydiver
        7
    skydiver  
       2012-10-10 10:20:00 +08:00   ❤️ 1
    @skyleft 概率算法有问题,打回去重算~
    skyleft
        8
    skyleft  
       2012-10-10 10:26:49 +08:00
    @skydiver 第一个不需要除n
    cabbala
        9
    cabbala  
       2012-10-10 10:31:01 +08:00
    Python打日志不用print啊,用logger打,而且还能控制打印的粒度。
    jianingy
        10
    jianingy  
       2012-10-10 10:38:24 +08:00   ❤️ 1
    @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
        11
    skydiver  
       2012-10-10 10:45:17 +08:00   ❤️ 1
    @kid7st
    @skyleft 其实简单说就是打印日志可以二分查找,单步只能一步一步跟踪,所以一个是O(log n)一个是O(n)
    haohaolee
        12
    haohaolee  
       2012-10-10 10:51:08 +08:00
    笑笑就好,有的还不能当真。用调试器又不光是单步,而且用调试器和打印日志也不矛盾
    kid7st
        13
    kid7st  
       2012-10-10 12:06:26 +08:00
    @skydiver 二分,这个明白了。thanks!
    holmesabc
        14
    holmesabc  
       2012-10-10 12:15:18 +08:00
    @haohaolee 同意

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

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

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

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

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

    Python的PEP8标准应该作为严格执行。
    jianingy
        22
    jianingy  
       2012-10-10 16:40:56 +08:00
    @013231 其实打印日志的问题上我们的理解也点不同。打印运行日志是必要的也是很有技巧的,大部分生产问题都可以通过运行日志定位。而我所尽量规避的是通过不停在代码中加print语句来调试程序的方式。
    nodexy
        23
    nodexy  
       2012-10-10 16:41:18 +08:00
    @BOYPT 他说的可能是 PSP
    cabbala
        24
    cabbala  
       2012-10-10 16:43:47 +08:00   ❤️ 1
    @jianingy 用logger取代print就好了,多简单的事情
    funagi
        25
    funagi  
       2012-10-10 18:24:27 +08:00
    我以前用断点多,现在用log多,不知道算是进步还是退步。
    现在偶尔还是会用断点,不过仅限于C#之类,感觉脚本语言用log更方便,所以python我用log。
    Sherlockhlt
        26
    Sherlockhlt  
       2012-10-11 17:07:34 +08:00
    一般我是先print,要是还找不到就debug,要是还找不到就去逛逛v2ex。。好吧我要去继续找bug了再见。
    Narcissu5
        27
    Narcissu5  
       2012-10-13 03:41:08 +08:00
    @013231 俺们家VS可以冻结线程,指定线程的完成顺序这个还真只能Debug
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1087 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 18:14 · PVG 02:14 · LAX 11:14 · JFK 14:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.