这会中断您的进程(除非您在线程中启动它),但您可以使用code 模块来启动 Python 控制台:
import code
code.interact()
这将一直阻塞,直到用户通过执行exit() 退出交互式控制台。
code 模块至少在 Python v2.6 中可用,可能还有其他版本。
我倾向于将此方法与我的 Linux 工作的信号结合使用(对于 Windows,请参见下文)。我把这个放在我的 Python 脚本的顶部:
import code
import signal
signal.signal(signal.SIGUSR2, lambda sig, frame: code.interact())
然后从带有kill -SIGUSR2 <PID> 的shell 触发它,其中<PID> 是进程ID。然后该进程停止它正在执行的任何操作并显示一个控制台:
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 v2.2 and above expose a Windows-specific signal SIGBREAK(通过按 CTRL+Pause/Break 触发)。这不会干扰正常的CTRL+C (SIGINT) 操作,因此是一个方便的替代方案。
因此,上述的可移植但略显丑陋的版本是:
import code
import signal
signal.signal(
vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"),
lambda sig, frame: code.interact()
)
这种方法的优点:
- 没有外部模块(所有标准 Python 内容)
- 在触发之前几乎不消耗任何资源(2x 导入)
这是我在生产环境中使用的代码,它将加载 WinPDB 的服务器端(如果可用)并回退到打开 Python 控制台。
# 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
print
print "Starting embedded RPDB2 debugger. Password is 'foobar'"
print
print
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