如何在eval()或exec()中以编程方式退出pdb而不显示输出
在我的Python代码中,有这么一行:
try:
result = eval(command, self.globals, self.locals)
except SyntaxError:
exec(command, self.globals, self.locals)
这个command
变量可以是任何字符串。因此,Python调试器pdb
可能会在eval
/exec
中启动,并且在eval
/exec
返回时仍然处于活动状态。我想要做的是确保在从eval
/exec
返回时,正常的程序执行能够继续。给你一个大概念,这就是我想要的行为:
try:
result = eval(command, self.globals, self.locals)
try: self.globals['pdb'].run('continue')
except: pass
except SyntaxError:
exec(command, self.globals, self.locals)
try: self.globals['pdb'].run('continue')
except: pass
但是,try
这一行在执行之前就已经在调试器中显示出来了,我并不想让调试器显示我的代码。而且,这样也并没有真正解决问题……我重复代码的原因是为了减少我代码中的调试工作,否则我可以在except
块之后再处理。
那么我该怎么做呢?
顺便提一下:
如果你尝试在IPython或bpython解释器中输入以下几行,你会发现它们有同样的问题,你可以进入它们的代码。
import pdb
pdb.set_trace()
next
但是如果你在标准的CPython解释器中这样做,你会返回到Python提示符。这显然是因为前两者是用Python实现的,而最后一个不是。但我希望即使所有代码都是Python时,也能得到相同的行为。
1 个回答
4
虽然我有点担心你在执行一个你无法控制的字符串,但我假设你已经考虑过这个问题。
我觉得最简单的方法是让调试工具(pdb)在每一步检查一下当前的调用状态,并在你回到想要的层级时自动继续。你可以通过简单的修补来实现这一点。在下面的代码中,我把它简化成了一个简单的执行,因为你真正想要的只是让调试工具在返回到特定函数时自动继续。在你不想追踪的函数里调用 Pdb().resume_here()。需要注意的是,这个继续是全局的,只有一个继续点,但我相信如果你想的话,可以修改这个。
如果你运行这段代码,你会在函数 foo()
里进入调试器,然后你可以逐步调试,但一旦你返回到 bar()
,代码就会自动继续执行。
例如:
import sys
from pdb import Pdb
def trace_dispatch(self, frame, event, arg):
if frame is self._resume_frame:
self.set_continue()
return
return self._original_trace_dispatch(frame, event, arg)
def resume_here(self):
Pdb._resume_frame = sys._getframe().f_back
# hotfix Pdb
Pdb._original_trace_dispatch = Pdb.trace_dispatch
Pdb.trace_dispatch = trace_dispatch
Pdb.resume_here = resume_here
Pdb._resume_frame = None
def foo():
import pdb
pdb.set_trace()
print("tracing...")
for i in range(3):
print(i)
def bar():
Pdb().resume_here()
exec("foo();print('done')")
print("returning")
bar()