一个对运行脚本、记录回溯进行采样的模块。
tripod的Python项目详细描述
安装
安装三脚架:
$ pip install tripod
配置
您可以使用以下环境变量来调整采样器:
# Log traceback of running script every 5 seconds TRIPOD_INTERVAL = 5
用法
运行三脚架:
$ python -m tripod.sampler ./some_script.py [Tripod] Sampling every 5.000000 seconds [Tripod] Writing output to: /tmp/slow_process_tkM6Rt.log
每隔5秒,看门狗就会被激活,并查看脚本的 堆栈并将回溯(包括所有本地堆栈变量)附加到 日志文件。
每个堆栈都附加到日志文件中,如下所示:
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 162, in _run_module_as_main "__main__", fname, loader, pkg_name) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code exec code in run_globals File "/Users/shayne/Code/tripod/tripod/sampler.py", line 128, in <module> main() File "/Users/shayne/Code/tripod/tripod/sampler.py", line 118, in main exec f.read() in globals(), globals() File "<string>", line 5, in <module> File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 351, in read data = self._sock.recv(rbufsize) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 553, in read s = self.fp.read(amt) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 380, in read data = self._sock.recv(left) Full backtrace with local variables: File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 162, in _run_module_as_main "__main__", fname, loader, pkg_name) Arguments: _run_module_as_main(mod_name='tripod.sampler', alter_argv=1) Local variables: {'alter_argv': 1, 'code': <code object <module> at 0x10ba09a30, file "/Users/shayne/Code/tripod/tripod/sampler.py", line 1>, 'fname': '/Users/shayne/Code/tripod/tripod/sampler.py', 'loader': <pkgutil.ImpLoader instance at 0x10ba0a368>, 'main_globals': {'SafePrettyPrinter': <class '__main__.SafePrettyPrinter'>, 'Timer': <class 'tripod.timer.Timer'>, '__builtins__': <module '__builtin__' (built-in)>, '__doc__': None, '__file__': 'slow.py', '__loader__': <pkgutil.ImpLoader instance at 0x10ba0a368>, '__name__': '__main__', '__package__': 'tripod', 'dt': <module 'datetime' from '/Users/shayne/pyenv/lib/python2.7/lib-dynload/datetime.so'>, 'f': <addinfourl at 4495809568 whose fp = <socket._fileobject object at 0x10bac70d0>>, 'formatvalue': <function formatvalue at 0x10bac1320>, 'inspect': <module 'inspect' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py'>, 'linecache': <module 'linecache' from '/Users/shayne/pyenv/lib/python2.7/linecache.pyc'>, 'main': <function main at 0x10bac1488>, 'os': <module 'os' from '/Users/shayne/pyenv/lib/python2.7/os.pyc'>, 'peek': <function peek at 0x10bac1410>, 'pprint': <module 'pprint' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pprint.py'>, 'spformat': <function spformat at 0x10ba649b0>, 'stack': <function stack at 0x10bac1398>, 'sys': <module 'sys' (built-in)>, 'tempfile': <module 'tempfile' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/tempfile.pyc'>, 'thread': <module 'thread' (built-in)>, 'urllib2': <module 'urllib2' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.pyc'>}, 'mod_name': 'tripod.sampler', 'pkg_name': 'tripod'} File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code exec code in run_globals Arguments: _run_code(code=<code object <module> at 0x10ba09a30, file "/Users/shayne/Code/tripod/tripod/sampler.py", line 1>, run_globals=<dict object at 0x7f9812c1dc40 (really long repr)>, init_globals=None, mod_name='__main__', mod_fname='/Users/shayne/Code/tripod/tripod/sampler.py', mod_loader=<pkgutil.ImpLoader instance at 0x10ba0a368>, pkg_name='tripod') Local variables: {'code': <code object <module> at 0x10ba09a30, file "/Users/shayne/Code/tripod/tripod/sampler.py", line 1>, 'init_globals': None, 'mod_fname': '/Users/shayne/Code/tripod/tripod/sampler.py', 'mod_loader': <pkgutil.ImpLoader instance at 0x10ba0a368>, 'mod_name': '__main__', ...loads more...
上面的示例显示请求线程在 f.read()在tripod拍摄快照时。
注意tripod只查看线程的堆栈。它没有 中断脚本,或以任何其他方式影响脚本。
注意事项
像dogslow一样,三脚架使用多线程。它有一个单独的后台线程来处理 计时器超时并获取回溯,以便原始脚本 线程不会中断。这有一些后果。
多线程和gil
在cpython中,gil(全局解释器锁)防止多个线程 同时执行python代码。只有当线程显式释放 它的锁在gil上,可以有第二个线程运行。
每当python程序 阻止解释器外部的调用,例如在执行IO时。
对于tripod,这意味着它只能对 很慢,因为他们正在进行IO、呼叫睡眠或忙着等待获取 自锁。
在大多数情况下这是好的。cpython的gil有问题的场景 当请求的线程在python代码中到达无限循环时 (或者是非常昂贵而且需要很长时间的合法python 执行),决不释放gil。即使tripod的看门狗 计时器确实可以运行,它无法记录堆栈。
联合程序和greenlet
Tripod用于同步配置。一个 使用专用线程(或单线程进程)的进程。
当使用“共同例程框架”运行时,其中提供多个请求 同时由一条线,回溯可能会变得毫无意义。