启动 Python 调试器,同时将模块作为脚本执行
Posted
技术标签:
【中文标题】启动 Python 调试器,同时将模块作为脚本执行【英文标题】:Launch Python debugger while simultaneously executing module as script 【发布时间】:2013-08-10 21:08:52 【问题描述】:在开发 Python 包时,使用-m
选项将包内的模块作为脚本运行以进行快速测试非常方便。例如,对于 somepackage
内部有模块 somemodule.py
,调用
python -m somepackage.somemodule
从somepackage
所在的目录运行somemodule.py
,就好像子模块是__main__
。如果包使用如here 所述的显式相对导入,则使用此调用语法尤其重要。
同样,使用-m
选项调试脚本也很方便,如
python -m pdb somescript.py
有没有办法同时做这两个?也就是说,我可以像调用脚本一样调用模块并同时启动到调试器中吗?我意识到我可以进入代码本身并在我想要中断的地方插入import pdb; pdb.set_trace()
,但我试图避免这种情况。
【问题讨论】:
【参考方案1】:有effortsunderway 可以在Python 本身中解决这个问题。看起来像 Python 3.7,你可以这样做:
python -m pdb -m somepackage.somemodule
我已经为较旧的 Python 版本(2.7+)提供了a backport:
pip install backports.pdb
python -m backports.pdb -m somepackage.somemodule
【讨论】:
python -m pdb -m path.to.module
在 python 3.9.5 中非常适合我【参考方案2】:
经过一段时间的试验,结果证明这种方法确实有效:
python -c "import runpy; import pdb; pdb.runcall(runpy.run_module, 'somepackage.somemodule', run_name='__main__')"
出于某种原因,使用pdb.runcall
而非pdb.run
很重要。
【讨论】:
pdb.run 需要一个字符串,而不是可调用的。python -c "import runpy; import pdb; pdb.run(\"runpy.run_module( 'somepackage.somemodule', run_name='__main__')\")"
也可以,但是比较麻烦【参考方案3】:
基于@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
【讨论】:
【参考方案4】:这是另一个也适用于命令行参数的选项。
将脚本的逻辑包装在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_line_args
必须是字符串列表,就像argv
一样)。
作为额外的奖励,当您的模块具有可导入的 main
函数时,您可以以相同的方式为其编写单元测试 =)
【讨论】:
【参考方案5】:这对我有用(使用 -m 选项将 python 模块作为脚本调试)
我创建了一个划痕
import runpy
if __name__ == '__main__':
runpy.run_module('somepackage.somemodule', run_name="__main__", alter_sys=True)
想法来自:Intellij/Pycharm can't debug Python modules
【讨论】:
以上是关于启动 Python 调试器,同时将模块作为脚本执行的主要内容,如果未能解决你的问题,请参考以下文章