python: is it possible to attach a console into a running process
我只想看看进程的状态,是否可以在进程中附加一个控制台,这样我就可以调用进程内部的函数并查看一些全局变量。
最好在不受影响的情况下运行进程(当然性能可能会下降一点)
这将中断您的进程(除非您在线程中启动它),但您可以使用
1 2 | import code code.interact() |
这将被阻止,直到用户通过执行
对于我的Linux工作,我倾向于将这种方法与信号结合使用(对于Windows,请参见下文)。我把它放在了我的python脚本的顶部:
1 2 3 | import code import signal signal.signal(signal.SIGUSR2, lambda sig, frame: code.interact()) |
然后从带有
1 2 3 4 5 | Python 2.6.2 (r262:71600, Oct 9 2009, 17:53:52) [GCC 3.4.2] on linux2 Type"help","copyright","credits" or"license" for more information. (InteractiveConsole) >>> |
一般来说,我将从那里加载远程调试器的服务器端组件,比如优秀的winpdb。
Windows不是符合POSIX的操作系统,因此不能提供与Linux相同的信号。但是,python 2.2及更高版本公开了一个特定于Windows的信号
因此,一个便携的,但有点难看的,上面的版本是:
1 2 3 4 5 6 | import code import signal signal.signal( vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"), lambda sig, frame: code.interact() ) |
这种方法的优点:
- 没有外部模块(所有标准的python工具)
- 在触发之前几乎不消耗任何资源(2x导入)
下面是我在生产环境中使用的代码,它将加载winpdb的服务器端(如果可用),并返回到打开Python控制台。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # Break into a Python console upon SIGUSR1 (Linux) or SIGBREAK (Windows: # CTRL+Pause/Break). To be included in all production code, just in case. def debug_signal_handler(signal, frame): del signal del frame try: import rpdb2 print"Starting embedded RPDB2 debugger. Password is 'foobar'" rpdb2.start_embedded_debugger("foobar", True, True) rpdb2.setbreak(depth=1) return except StandardError: pass try: import code code.interact() except StandardError as ex: print"%r, returning to normal program flow" % ex import signal try: signal.signal( vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR1"), debug_signal_handler ) except ValueError: # Typically: ValueError: signal only works in main thread pass |
如果您可以访问程序的源代码,则可以相对轻松地添加此功能。
见配方576515:
引述:
This provides code to allow any python
program which uses it to be
interrupted at the current point, and
communicated with via a normal python
interactive console. This allows the
locals, globals and associated program
state to be investigated, as well as
calling arbitrary functions and
classes.To use, a process should import the
module, and call listen() at any point
during startup. To interrupt this
process, the script can be run
directly, giving the process Id of the
process to debug as the parameter.
rconsole提供了大致相同概念的另一个实现。从文档中:
rconsole is a remote Python console
with auto completion, which can be
used to inspect and modify the
namespace of a running script.To invoke in a script do:
1 2 | from rfoo.utils import rconsole rconsole.spawn_server() |
To attach from a shell do:
1 | $ rconsole |
Security note: The rconsole listener
started with spawn_server() will
accept any local connection and may
therefore be insecure to use in shared
hosting or similar environments!
使用吡嗪外壳。我不敢相信它能这么好地工作,但确实如此。"给它一个PID,得到一个外壳"。
1 2 3 4 5 6 7 8 9 10 11 12 13 | $ sudo pip install pyrasite $ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # If YAMA activated, see below. $ pyrasite-shell 16262 Pyrasite Shell 2.0 Connected to 'python my_script.py' Python 2.7.6 (default, Jun 22 2015, 17:58:13) [GCC 4.8.2] on linux2 Type"help","copyright","credits" or"license" for more information. >>> globals() >>> print(db_session) >>> run_some_local_function() >>> some_existing_local_variable = 'new value' |
这将启动python shell,以访问运行python进程的globals()和locals()变量,以及其他奇妙的事情。
仅在Ubuntu上进行了个人测试,但似乎也迎合了OSX。
根据这个答案改编。
注:只有在
为什么不简单地使用PDB模块?它允许您停止脚本,检查元素值,并逐行执行代码。由于它是基于Python解释器构建的,所以它还提供了经典解释器提供的特性。要使用它,只需在代码中放置这两行代码,您希望在其中停止并检查它:
1 2 | import pdb pdb.set_trace() |
另一种不向python脚本添加内容的可能性描述如下:
https://wiki.python.org/moin/debuggingwithgdb
不幸的是,这个解决方案还需要一些预先考虑,至少在某种程度上,您需要使用一个包含调试符号的Python版本。
使用pycharm,我在Ubuntu中无法连接到进程。解决这个问题的方法是禁用yama。有关更多信息,请参阅askubuntu
1 | echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope |