代码之家  ›  专栏  ›  技术社区  ›  Mathias

如何以编程方式退出在eval()或exec()中启动的pdb而不显示输出

  •  3
  • Mathias  · 技术社区  · 15 年前

    在我的python代码中有这样一行:

    try:
        result = eval(command, self.globals, self.locals)
    except SyntaxError:
        exec(command, self.globals, self.locals)
    

    command 变量可以是任何字符串。因此python调试器 pdb 可能是从 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
    

    1 回复  |  直到 11 年前
        1
  •  3
  •   Duncan    15 年前

    虽然我有点担心您正在评估/执行一个您无法控制的字符串,但我假设您已经仔细考虑过了。

    我认为最简单的事情就是说服pdb检查每个步骤上的堆栈帧,并在您返回到所需级别时自动恢复。你可以通过简单的热修复来做到这一点。在下面的代码中,我将它简化为一个简单的eval,因为您真正需要的是在返回到特定函数时自动恢复pdb。调用Pdb()。在不希望跟踪的函数中继续。N、 B.恢复是全球性的,只有一个恢复点,但我相信如果你愿意,你可以修改。

    如果运行代码,则将在函数中输入调试器 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()
    
    推荐文章