启动Python调试器,同时将模块作为脚本执行

时间:2013-08-10 21:08:52

标签: python pdb

在开发Python包时,使用-m选项将包内的模块作为脚本进行快速测试非常方便。例如,对于其中包含模块somepackage的{​​{1}},请调用

somemodule.py
来自python -m somepackage.somemodule 所在目录的

将运行somepackage,就好像子模块是somemodule.py一样。如果程序包使用here所述的显式相对导入,则使用此调用语法尤为重要。

同样,使用__main__选项调试脚本也很方便,如

-m

有没有办法同时做两件事?也就是说,我可以将模块称为脚本并同时启动调试器吗?我意识到我可以进入代码本身并将python -m pdb somescript.py 插入我想要破解的地方,但我试图避免这种情况。

5 个答案:

答案 0 :(得分:8)

经过一段时间的实验,结果证明这种方法确实有效:

python -c "import runpy; import pdb; pdb.runcall(runpy.run_module, 'somepackage.somemodule', run_name='__main__')"

出于某种原因,使用pdb.runcall而非pdb.run非常重要。

答案 1 :(得分:6)

efforts underway在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

答案 2 :(得分:0)

这是另一个也适用于命令行参数的选项。

将脚本的逻辑包装在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

或者可以通过pdb直接调用main()来运行它:

$ python -c "import pdb; import argdemo; pdb.runcall(argdemo.main, ['2'])"
(Pdb) continue
> The number is 2

(请注意,cmd_line_args必须是一个字符串列表,就像argv一样。

作为额外的好处,当您的模块具有可导入的main功能时,您可以以相同的方式为其编写单元测试=)

答案 3 :(得分:0)

在@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 Path中的任何位置(当前目录有效),然后您可以调用:

python -m mpdb somepackage.somemodule even with args

答案 4 :(得分:0)

这对我有用(使用-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