启动Python调试器,同时以脚本形式执行模块
在开发Python包时,使用启动Python调试器,同时以脚本形式执行模块,python,pdb,Python,Pdb,在开发Python包时,使用-m选项将包内的模块作为脚本运行以进行快速测试非常方便。例如,对于包含模块somemodule.py的somepackage,调用 python -m somepackage.somemodule 从somepackage所在的目录中,将运行somemodule.py,就像子模块是\uuuuuu main\uuuu一样。如果包使用如上所述的显式相对导入,则使用此调用语法尤其重要 类似地,使用-m选项调试脚本也很方便,如中所示 python -m pdb somesc
-m
选项将包内的模块作为脚本运行以进行快速测试非常方便。例如,对于包含模块somemodule.py
的somepackage
,调用
python -m somepackage.somemodule
从somepackage
所在的目录中,将运行somemodule.py
,就像子模块是\uuuuuu main\uuuu
一样。如果包使用如上所述的显式相对导入,则使用此调用语法尤其重要
类似地,使用-m
选项调试脚本也很方便,如中所示
python -m pdb somescript.py
有没有办法同时做到这两个方面?也就是说,我可以像调用脚本一样调用模块并同时启动调试器吗?我意识到我可以进入代码本身并插入
importpdb;pdb.set_trace()
在我想中断的地方,但我正试图避免这种情况。经过一段时间的试验,结果证明这种方法确实有效:
python -c "import runpy; import pdb; pdb.runcall(runpy.run_module, 'somepackage.somemodule', run_name='__main__')"
出于某种原因,在
pdb.run
上使用pdb.runcall
是很重要的。这里还有另一个选项也适用于命令行参数
通常最好将脚本的逻辑封装在main
函数中。然后,您可以让main
接受可选的参数列表,以覆盖sys.argv
。下面是一个名为argdemo.py
的示例:
def main(cmd_line_args=None):
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("number", help="a number", type=int)
# allow cmd_line_args to override sys.argv
if cmd_line_args is None:
args = parser.parse_args()
else:
args = parser.parse_args(cmd_line_args)
print("The number is {}".format(args.number))
if __name__ == '__main__':
main()
此模块可以正常运行:
$ python -m argdemo 2
> The number is 2
也可以通过直接调用main()
使用pdb
运行:
$ python -c "import pdb; import argdemo; pdb.runcall(argdemo.main, ['2'])"
(Pdb) continue
> The number is 2
(注意,cmd\u line\u args
必须是字符串列表,就像argv
一样)
作为额外的好处,当您的模块具有可导入的
main
函数时,您可以用相同的方式为其编写单元测试=)基于@jed的答案,我构建了这个模块:
import pdb
import runpy
import sys
def main():
module = sys.argv[1]
sys.argv[1:] = sys.argv[2:]
pdb.runcall(runpy.run_module, module, run_name='__main__')
__name__ == '__main__' and main()
将该模块作为mpdb.py
放在Python路径中的任何位置(当前目录有效),然后可以调用:
python -m mpdb somepackage.somemodule even with args
在Python中有很多方法可以解决这个问题。与Python 3.7类似,您可以执行以下操作:
python -m pdb -m somepackage.somemodule
我还提供了较旧的Python版本(2.7+):
这对我很有用(将python模块作为带有-m选项的脚本进行调试)
我造成了一个划痕
import runpy
if __name__ == '__main__':
runpy.run_module('somepackage.somemodule', run_name="__main__", alter_sys=True)
这个想法来自:pdb.run需要一个字符串,而不是一个可调用的字符串
python-c“import runpy;import pdb;pdb.run(\”runpy.run\u模块('somepackage.somemodule',run\u名称=''''''''\')”)”
同样有效,但更麻烦
import runpy
if __name__ == '__main__':
runpy.run_module('somepackage.somemodule', run_name="__main__", alter_sys=True)