Friday, May 13, 2011

Python 3.3 新增了 faulthandler 模块,用来帮助调试

原文链接: New faulthandler module in Python 3.3 helps debugging

当用户报告你的程序崩溃了或者僵死了,有时你只能试着搜集有用信息,概括当时 的场景,以便能够重现错误。即使有了一个可靠的用户场景,作为开发者的你经常会 无法重现错误,因为你们的环境相差很大,比如操作系统和编译器。当用户安装了调试 工具时你会幸运一点,但大部分情况下你只能等待其他人能够从这相同的情形下获得 更多的有用信息。

致命错误

Python 3.3 中新引入的模块可以帮助处理这个问题: faulthandler. faulthandler 在Python碰到类似于段错误,除0, 中止程序和总线故障等的致命错误(fatal error) 时 能dump 出 trackback。 你可以通过在你的应用程序中加入 faulthandler.enable(), 或者调用Python 可执行程序时提供 -X faulthandler 参数,或者设置 PYTHONFAULTHANDLER=1 环境变量来启用该功能。 输出类似如下

Fatal Python error: Segmentation fault

Current thread 0x00007f7babc6b700:
  File "Lib/test/crashers/gc_inspection.py", line 29 in g
  File "Lib/test/crashers/gc_inspection.py", line 32 in <module>
Segmentation fault

超时

通过调用 faulthandler.dump_tracebacks_later(timeout), faulthandler 能 在超时时dump出traceback。再次调用该函数可以重启计时器,或者调用 faulthandler.cancel_dump_tracebacks_later() 来关闭计时器。 输出类似如下:

Timeout (0:01:00)!
Current thread 0x00007f987d459700:
  File "Lib/test/crashers/infinite_loop_re.py", line 20 in <module>

使用 repeat=True 选项可以在每 timeout 秒后dump一次traceback, 或者用 exit=True 选项使程序立即不安全(不会把文件全部写入磁盘)退出。

用户信号

如果你有程序运行所在的主机的访问权限,你可以使用 faulthandler.register(signal) 来注册一个处理信号句柄, 当 single 信号收到时,可以dump 出 traceback。 在Unix系统上,你可以使用 SIGUSER1 信号: kill -USER1 <pid> 将把当前的 traceback 给dump 出来。这个特性在Windows系统上时没有的。 输出类似如下:

Current thread 0x00007fdc3da74700:
  File "Lib/test/crashers/infinite_loop_re.py", line 19 in <module>

另外一种方式是在你的程序中显式调用 faulthandler.dump_traceback() .

安全问题 以及 输出文件

由于安全因素 faulthandler 默认时关闭的, 主要是因为它保存了 sys.stderr 的文件描述符, 并把trackback写入那个文件描述符。如果 sys.stderr 被关闭了, 但这个文件描述符被重用了,那这个文件描述符可能是个socket,管道,一个关键文件或者 其他什么。默认情况下, faulthandler 把traceback 写到 sys.stderr 中, 但你可以指定其他文件。 更多相关的信息可以查阅 faulthandler 文档.

旧版Python的第三方模块

PyPI 上``faulthandler`` 作为Python 2.5版本到 3.2版本的第三方模块维护。 Python 3.3 标准模块和第三方模块的主要区别时 dump_tracebacks_later 的实现方式: Python 3.3 使用线程的锁超时,而第三方库使用了 SIGALRMalarm()

作为Python 3.3的新特性, 锁超时的精度是1微妙。旧版Python上的 alarm() 的精度时1秒, SIGALRM 信号可能会中断当前的系统调用, 使系统以 EINTR 错误 失败。

早已取得成功

faulthandler 新模块已经在我们的buildbot项目中帮助我们跟踪竞争状态。我们希望 它也能在你的程序中帮助你。

No comments:

Post a Comment