Python 调试新思路

New Ideas on Python Debugging
 

About me

  • Working for Google

  • Use Python since 2012

  • 《捕蛇者说》播客创始人/pythonhunter.org

@laike9m

几种错误

  1. 生成 bytecode 出错(e.g. Syntax Error)
     
  2. 程序异常退出(e.g. Unhandled Exception)
     
  3. 程序正常执行,但结果不符合预期
     
  4. 程序正常执行且结果正确,但资源占用异常 (e.g. Memory leak)

几种错误

  1. 生成 bytecode 出错(e.g. Syntax Error)
     
  2. 程序异常退出(e.g. Unhandled Exception)
     
  3. 程序正常执行,但结果不符合预期
     
  4. 程序正常执行且结果正确,但资源占用异常

调试方法

  • print()
  • Logging
  • Debugger
    • pdb(ipdb, pudb, etc)
    • PyCharm
    • VS Code

调试方法

  • print()
  • Logging
  • Debugger
    • pdb(ipdb, pudb, etc)
    • PyCharm
    • VS Code

print()

On the other hand, often the quickest way to debug a program is to add a few print statements to the source: the fast edit-test-debug cycle makes this simple approach very effective. 
                                                                 -- Guido van Rossum
                                                                                                                          http://python.org/doc/essays/blurb.html

print()

I don't like debuggers. Never have, probably never will.

                                                                        -- Linus Torvalds
                                                                                                                                              https://lwn.net/2000/0914/a/lt-debugger.php3

print() 的优点

  • 开箱即用
     
  • 没有多余信息
     
  • 一般不影响程序执行
     
  • “这段代码跑没跑?”

print() 的缺点

  • 需要对代码熟悉
     
  • 需要反复修改代码
     
  • 缺乏上下文
     
  • 输出难于管理

调试方法

  • print()
  • Logging
  • Debugger
    • pdb(ipdb, pudb, etc)
    • PyCharm
    • VS Code

Logging

import logging

logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

Logging 的优点

  • 可配置

  • 方便管理(e.g. Sentry)

  • 更丰富的上下文(filename, lineno, etc)

Logging 的缺点

  • 需要配置
    logger = logging.getLogger()
    handler = logging.StreamHandler()
    formatter = logging.Formatter(
          '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    logger.setLevel(logging.DEBUG)
    
  • 未必开箱即用
  • 依然缺乏足够的上下文

调试方法

  • print()
  • Logging
  • Debugger
    • pdb(ipdb, pudb, etc)
    • PyCharm
    • VS Code

Debugger 的优点

  • 功能强大
     
  • 不需要对代码熟悉
     
  • 快速定位未知问题

Debugger 的缺点

  • 依赖 库/编辑器/IDE
     
  • 一定的学习成本
     
  • 无法持久化输出
     
  • 性能

你是否曾经...

  • 加了20个 print 却找不到错误,

  • 单步跟了半天,然而问题并不在那,

  • 思考被开会打断,只能从头开始想,

  • 试图调试别人的代码,然后被绕晕了,

问题:var 明明应该等于 foo

               为啥却是 bar  🤔🤔

 

解决:弄清 bar 这个值是怎么来的

调试的本质

就没有更直接

方法吗?

Automate manual work

将手动操作自动化

An Example: PySnooper

with pysnooper.snoop():
    lower = min(lst)
    upper = max(lst)
    mid = (lower + upper) / 2
New var:....... lst = [681, 267, 74, 832, 284, 678, ...]
09:37:35.881721 line        10         lower = min(lst)
New var:....... lower = 74
09:37:35.882137 line        11         upper = max(lst)
New var:....... upper = 832
09:37:35.882304 line        12         mid = (lower + upper) / 2
74 453.0 832
New var:....... mid = 453.0

What We Have

print Debugger
手动
自动化

自动化调试

Cyberbrain (电子脑)

github.com/laike9m/Cyberbrain

开会了

水豚(capybara)

Quiz Time

请说出之前那段代码的文件名

  • 变量追踪溯源
  • 排除无关代码干扰
  • 精确定位 bug
  • 调试信息持久化

Cyberbrain 做了什么

 

  • 分治全局分析(难) → 相邻行分析(易)
     
  • 先记录所有需要的信息,再做分析

Cyberbrain 做了什么

  • cyberbrain.init()
    sys.settrace(tracer: Callable[FrameType])
    • frame object
       ⮑  source location
       ⮑  vars
       ⮑  callsite
  • cyberbrain.register(foo)
    • 逆向遍历所有行,分析变量变化
    • 可视化

分析变量变化

What's Next

  • Fix bugs

  • 优化内存使用

  • 多线程支持

  • 多变量支持,条件触发

  • 更好的可视化

可视化

  • 更优雅的显示

可视化

  • 可交互
  • 更加智能

合作者招募中!

Collaborators Needed

总结

  • 传统 debug 方法:print, logging, debugger

  • 痛点:无法直接对变量进行溯源

  • Cyberbrain 自动化调试

    • 变量追踪溯源
    • 排除无关代码干扰
    • 精确定位 bug
    • 调试信息持久化
    • P.S. 感谢 @thautwarm, @laixintao, @zhangyangyu

  谢谢大家!

 

Q & A