pstack
Advanced tools
+1
-1
| Metadata-Version: 1.0 | ||
| Name: pstack | ||
| Version: 0.3 | ||
| Version: 0.4 | ||
| Summary: Tool to print python thread and greenlet stacks | ||
@@ -5,0 +5,0 @@ Home-page: https://github.com/wooparadog/pstack/ |
| Metadata-Version: 1.0 | ||
| Name: pstack | ||
| Version: 0.3 | ||
| Version: 0.4 | ||
| Summary: Tool to print python thread and greenlet stacks | ||
@@ -5,0 +5,0 @@ Home-page: https://github.com/wooparadog/pstack/ |
+1
-1
@@ -12,3 +12,3 @@ # !/usr/bin/env python | ||
| name="pstack", | ||
| version='0.3', | ||
| version='0.4', | ||
| description="Tool to print python thread and greenlet stacks", | ||
@@ -15,0 +15,0 @@ author="Haochuan Guo", |
+48
-18
| #! /usr/bin/env python | ||
| # -*- coding: utf-8 -*- | ||
| import os | ||
| import subprocess | ||
| import tempfile | ||
| import platform | ||
@@ -31,5 +33,37 @@ import click | ||
| def print_stack(pid, include_greenlet=False, verbose=False): | ||
| def make_gdb_args(pid, command): | ||
| statements = [ | ||
| r'call PyGILState_Ensure()', | ||
| r'call PyRun_SimpleString("exec(\"%s\")")' % command, | ||
| r'call PyGILState_Release($1)', | ||
| ] | ||
| arguments = ['gdb', '-p', str(pid), '-batch'] | ||
| arguments.extend("-eval-command='%s'" % s for s in statements) | ||
| return arguments | ||
| def make_lldb_args(pid, command): | ||
| statements = [ | ||
| r'expr (void *) $gil = (void *) PyGILState_Ensure()', | ||
| r'expr (void) PyRun_SimpleString("exec(\"%s\")")' % command, | ||
| r'expr (void) PyGILState_Release($gil)', | ||
| ] | ||
| arguments = ['lldb', '-p', str(pid), '--batch'] | ||
| arguments.extend('--one-line=%s' % s for s in statements) | ||
| return arguments | ||
| def print_stack(pid, include_greenlet=False, debugger=None, verbose=False): | ||
| """Executes a file in a running Python process.""" | ||
| tmp_file = tempfile.mktemp() | ||
| make_args = make_gdb_args | ||
| environ = dict(os.environ) | ||
| if ( | ||
| debugger == 'lldb' or | ||
| (debugger is None and platform.system().lower() == 'darwin') | ||
| ): | ||
| make_args = make_lldb_args | ||
| # fix the PATH environment variable for using built-in Python with lldb | ||
| environ['PATH'] = '/usr/bin:%s' % environ.get('PATH', '') | ||
| tmp_fd, tmp_path = tempfile.mkstemp() | ||
| commands = [] | ||
@@ -43,14 +77,5 @@ commands.append(FILE_OPEN_COMMAND) | ||
| gdb_cmds = [ | ||
| 'PyGILState_Ensure()', | ||
| 'PyRun_SimpleString("exec(\\"%s\\")")' % ( | ||
| command % tmp_file | ||
| ), | ||
| 'PyGILState_Release($1)', | ||
| ] | ||
| cmd = 'gdb -p %d -batch %s' % ( | ||
| pid, ' '.join(["-eval-command='call %s'" % cmd for cmd in gdb_cmds]) | ||
| ) | ||
| args = make_args(pid, command % tmp_path) | ||
| process = subprocess.Popen( | ||
| cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
| args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=environ) | ||
| out, err = process.communicate() | ||
@@ -60,13 +85,18 @@ if verbose: | ||
| print err | ||
| with open(tmp_file) as fo: | ||
| print fo.read() | ||
| print os.read(tmp_fd, 10240) | ||
| @click.command() | ||
| CONTEXT_SETTINGS = { | ||
| 'help_option_names': ['-h', '--help'], | ||
| } | ||
| @click.command(context_settings=CONTEXT_SETTINGS) | ||
| @click.argument('pid', required=True, type=int) | ||
| @click.option('--include-greenlet', default=False, is_flag=True, | ||
| help="Also print greenlet stacks") | ||
| @click.option('-d', '--debugger', type=click.Choice(['gdb', 'lldb'])) | ||
| @click.option('-v', '--verbose', default=False, is_flag=True, | ||
| help="Verbosely print error and warnings") | ||
| def stack(pid, include_greenlet, verbose): | ||
| def stack(pid, include_greenlet, debugger, verbose): | ||
| '''Print stack of python process. | ||
@@ -76,5 +106,5 @@ | ||
| ''' | ||
| return print_stack(pid, include_greenlet, verbose) | ||
| return print_stack(pid, include_greenlet, debugger, verbose) | ||
| if __name__ == '__main__': | ||
| stack() |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
4678
28.09%103
28.75%