gpt4 book ai didi

python - 从程序运行 python 调试 session ,而不是从控制台

转载 作者:太空狗 更新时间:2023-10-30 00:57:27 25 4
gpt4 key购买 nike

我正在写一个小的python IDE,我想添加简单的调试。我不需要 winpdb 的所有功能。
如何启动一个 python 程序(按文件名),断点设置在行号,以便它运行到该行号并停止?
请注意,我不想从命令行执行此操作,也不想编辑源代码(例如,通过插入 set_trace)。我不希望它停在第一行,所以我必须从那里运行调试器。我已经尝试了 pdb 和 bdb 的所有明显方法,但我一定遗漏了一些东西。

最佳答案

几乎唯一可行的方法(据我所知)是在 IDE 中将 Python 作为子进程运行。这避免了当前 Python 解释器的“污染”,这使得程序很可能以与您独立启动它的方式相同的方式运行。 (如果您对此有疑问,请检查子进程环境。)以这种方式,您可以使用以下方法在“ Debug模式”下运行脚本

p = subprocess.Popen(args=[sys.executable, '-m', 'pdb', 'scriptname.py', 'arg1'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)

这将在调试器提示符下启动 Python。您需要运行一些调试器命令来设置断点,您可以这样做:
o,e = p.communicate('break scriptname.py:lineno')

如果这有效, o应该是Python解释器设置断点后的正常输出, e应该是空的。我建议您尝试一下并在代码中添加一些检查以确保断点设置是否正确。

之后,您可以启动程序运行
p.communicate('continue')

此时,您可能希望将输入、输出和错误流连接到嵌入到 IDE 中的控制台。您可能需要使用事件循环来执行此操作,大致如下所示:
while p.returncode is None:
o,e = p.communicate(console.read())
console.write(o)
console.write(e)

您应该将该代码段视为有效的伪代码,因为取决于您的控制台的工作方式,可能需要进行一些修补才能使其正确。

如果这看起来过于困惑,您可能可以使用 Python 的 pdb 的功能稍微简化该过程。和 bdb模块(我猜分别是“Python 调试器”和基本调试器)。关于如何做到这一点的最佳引用是 pdb 模块本身的源代码。基本上,模块职责的划分方式是 bdb 处理“幕后”调试器功能,如设置断点,或停止和重新启动执行; pdb 是一个包装器,用于处理用户交互,即读取命令和显示输出。

对于集成 IDE 的调试器,调整 pdb 的行为是有意义的。我能想到的两种方式的模块:
  • 让它在初始化期间自动设置断点,而不必明确发送文本命令来这样做
  • 让它从 IDE 的控制台获取输入并将输出发送到您的 IDE 控制台

  • 通过子类化 pdb.Pdb 应该很容易实现这两个更改.您可以创建一个子类,其初始化程序将断点列表作为附加参数:
    class MyPDB(pdb.Pdb):
    def __init__(self, breakpoints, completekey='tab',
    stdin=None, stdout=None, skip=None):
    pdb.Pdb.__init__(self, completekey, stdin, stdout, skip)
    self._breakpoints = breakpoints

    实际设置断点的逻辑位置是在调试器读取其 .pdbrc 之后。文件,发生在 pdb.Pdb.setup方法。要执行实际设置,请使用 set_break方法继承自 bdb.Bdb :
        def setInitialBreakpoints(self):
    _breakpoints = self._breakpoints
    self._breakpoints = None # to avoid setting breaks twice
    for bp in _breakpoints:
    self.set_break(filename=bp.filename, line=bp.line,
    temporary=bp.temporary, conditional=bp.conditional,
    funcname=bp.funcname)

    def setup(self, f, t):
    pdb.Pdb.setup(self, f, t)
    self.setInitialBreakpoints()

    这段代码适用于每个被传递的断点,例如一个命名元组。您也可以尝试只构建 bdb.Breakpoint直接实例,但我不确定这是否能正常工作,因为 bdb.Bdb维护自己的断点信息。

    接下来,您需要创建一个新的 main以相同方式运行的模块的方法 pdb运行。在某种程度上,您可以复制 main方法来自 pdb (当然还有 if __name__ == '__main__' 语句),但是您需要通过某种方式对其进行扩充,以传递有关其他断点的信息。我的建议是将断点从 IDE 写入临时文件,并将该文件的名称作为第二个参数传递:
    tmpfilename = ...
    # write breakpoint info
    p = subprocess.Popen(args=[sys.executable, '-m', 'mypdb', tmpfilename, ...], ...)
    # delete the temporary file

    然后在 mypdb.main() ,您将添加如下内容:
    def main():
    # code excerpted from pdb.main()
    ...
    del sys.argv[0]

    # add this
    bpfilename = sys.argv[0]
    with open(bpfilename) as f:
    # read breakpoint info
    breakpoints = ...
    del sys.argv[0]
    # back to excerpt from pdb.main()

    sys.path[0] = os.path.dirname(mainpyfile)

    pdb = Pdb(breakpoints) # modified

    现在您可以像使用 pdb 一样使用新的调试器模块。 ,除了您不必明确发送 break进程开始前的命令。这样做的好处是,您可以直接将 Python 子进程的标准输入和输出 Hook 到您的控制台,如果它允许您这样做的话。

    关于python - 从程序运行 python 调试 session ,而不是从控制台,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7707822/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com