21

在开发 Python 包时,使用该-m选项将包内的模块作为脚本运行以进行快速测试非常方便。例如,对于里面somepackage的模块,调用somemodule.py

python -m somepackage.somemodule

somepackage驻留的目录中运行somemodule.py,就好像子模块是__main__. 如果包使用此处所述的显式相对导入,则使用此调用语法尤其重要。

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

python -m pdb somescript.py

有什么办法可以同时做到这两点吗?也就是说,我可以像调用脚本一样调用模块并同时启动到调试器中吗?我意识到我可以进入代码本身并插入import pdb; pdb.set_trace()我想要中断的地方,但我试图避免这种情况。

4

5 回答 5

17

Python本身正在努力 解决这个问题。看起来像 Python 3.7,你可以这样做:

python -m pdb -m somepackage.somemodule

而且我为旧的 Python 版本(2.7+)提供了一个反向移植:

pip install backports.pdb
python -m backports.pdb -m somepackage.somemodule
于 2018-01-26T16:35:15.277 回答
10

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

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

出于某种原因,使用pdb.runcalloverpdb.run很重要。

于 2013-08-14T20:01:13.240 回答
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
于 2018-01-26T15:21:47.303 回答
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功能时,您可以以相同的方式为其编写单元测试 =)

于 2016-07-24T18:15:05.397 回答
0

这对我有用(调试 python 模块作为带有 -m 选项的脚本)

我创建了一个划痕

import runpy

if __name__ == '__main__':
    runpy.run_module('somepackage.somemodule', run_name="__main__", alter_sys=True)

想法取自:Intellij/Pycharm 无法调试 Python 模块

于 2018-08-02T13:03:25.430 回答