我正在编写一个小的Python IDE,我想添加简单的调试。我不需要winpdb的所有功能。 如何启动一个python程序(通过文件名)并将一个断点设置为行号,以使其运行到该行号并暂停? 请注意,我不想从命令行执行此操作,并且我不想编辑源代码(例如,通过插入set_trace)。我不希望它停在第一行,所以我必须从那里运行调试器。我已经用pdb和bdb尝试了所有显而易见的方法,但我必须缺少一些东西。从程序运行python调试会话,而不是从控制台运行
回答
几乎是唯一可行的方法(据我所知)是从您的IDE中运行Python作为子进程。这样可以避免当前Python解释器造成的“污染”,这使得程序运行的可能性与您独立开始运行的可能性相当。 (如果你有这样的问题,检查进程环境中)。在这种方式下,你可以使用
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集成的调试器,它将有助于调节t时的pdb
模块的,我能想到的两种行为:
- 初始化过程中,系统将自动设置断点,您无需显式地发送文本命令这样做
- 使其采取从输入并将输出发送到您的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
相同的方式运行。在某种程度上,您可以从pdb
(和当然的if __name__ == '__main__'
声明)复制main
方法,但您需要用某种方式来扩充它,以传入有关其他断点的信息。什么我建议是写断点从你的IDE中的临时文件,并作为第二个参数传递一个文件的名称:在mypdb.main()
tmpfilename = ...
# write breakpoint info
p = subprocess.Popen(args=[sys.executable, '-m', 'mypdb', tmpfilename, ...], ...)
# delete the temporary file
然后,你会增加这样的事情:
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子进程的标准输入和输出挂接到控制台。
感谢您的意见。但是,一旦到达p.communicate('continue'),我就会收到ValueError:关闭文件的I/O操作。 在Popen中使用close_fds = False并没有帮助... –
@antwin:请记住,所有这些本质上都是伪代码。如果你只是运行它,当然你会得到各种各样的错误。您需要根据自己的项目来调整它,但是我无法告诉您任何有关您的源代码的信息。 –
确实!因此,我将您的建议解压到以下文件中:#!/ usr/bin/python import sys,subprocess fileName ='/tmp/test.py' lineno = 4 p = subprocess.Popen(args = [sys.executable ,'-m','pdb',fileName], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) cmd ='break%s:%d'%(fileName,lineno ); print cmd o,e = p.communicate(cmd) p.communicate('continue') 它应该工作,并且我以前使用过类似的方法,但它仍然给出ValueError:关闭文件的I/O操作第一次沟通之后... –
- 1. jquery代码不会从页脚加载运行,而是从控制台运行
- 2. 从控制台运行gimp
- 3. 运行从SBT控制台
- 4. 从控制台运行java
- 5. 试图从控制台应用程序运行WebTest
- 6. IO程序不能从控制台运行,但它通过Eclipse(Java)运行
- 7. 从其他控制台应用程序运行控制台应用程序
- 8. 如何从控制台应用程序运行程序?
- 9. 从Windows XAML应用程序运行控制台应用程序
- 10. 从SciTE运行时控制台程序无法正确执行
- 11. 调试!程序不会运行
- 12. 如何判断是否在Linux控制台中运行而不是在ssh会话中运行?
- 13. 从控制器的Symfony3控制台运行控制台命令
- 14. 如何测试是否从CakePHP控制台运行?
- 15. 从cmd.exe运行时,基于C的控制台应用程序崩溃,在VS2008调试器中运行良好?
- 16. 从Python运行Java程序
- 17. 运行C#控制台应用程序
- 18. 无控制台运行Win32程序“silient”
- 19. Java JDBC |无法从控制台运行
- 20. 从控制台运行symfony动作
- 21. 从rails控制台运行迁移
- 22. 我如何从java控制台运行控制台应用程序?
- 23. 使用Windows调度程序运行控制台应用程序
- 24. 命令从命令行运行,而不是从cron运行?
- 25. 运行python的行为从python而不是命令行
- 26. 从VBA运行Telnet会话
- 27. 从Windows窗体运行控制台应用程序
- 28. 如何从rails控制台运行初始化程序?
- 29. 从system32文件夹运行控制台应用程序
- 30. 从C#控制台应用程序运行CMD?
所以你不想使用命令行,而且你不想编辑源代码......你还想过其他什么方式? – Amber