Launch Python debugger while simultaneously executing module as script

前端 未结 5 1428
你的背包
你的背包 2020-12-14 09:21

When developing a Python package, it\'s very convenient to use the -m option to run modules inside the package as scripts for quick testing. For example, for

相关标签:
5条回答
  • 2020-12-14 09:29

    This worked for me (debug python module as a script with -m option)

    I created a scratch

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

    idea taken from: Intellij/Pycharm can't debug Python modules

    0 讨论(0)
  • 2020-12-14 09:33

    There are efforts underway to solve this in Python itself. Looks like with Python 3.7, you can do:

    python -m pdb -m somepackage.somemodule
    

    And I've provided a backport for older Python versions (2.7+):

    pip install backports.pdb
    python -m backports.pdb -m somepackage.somemodule
    
    0 讨论(0)
  • 2020-12-14 09:33

    Building on @jed's answer, I built this module:

    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()
    

    Put that module as mpdb.py anywhere in your Python Path (current directory works), then you may invoke:

    python -m mpdb somepackage.somemodule even with args
    
    0 讨论(0)
  • 2020-12-14 09:43

    After experimenting with this for quite some time, it turns out that this approach actually works:

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

    For some reason, the use of pdb.runcall over pdb.run is important.

    0 讨论(0)
  • 2020-12-14 09:51

    Here's another option that also works with command line arguments.

    It's generally a good idea to wrap your script's logic in a main function. You can then have main take in an optional list of arguments to override sys.argv. Here's an example called 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()
    

    This module can be run as usual:

    $ python -m argdemo 2
    > The number is 2
    

    Or it can be run with pdb by calling main() directly:

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

    (Notice that cmd_line_args has to be a list of strings just like argv would be).

    As an added bonus, when your module has an import-able main function, you can write unit tests for it in the same way =)

    0 讨论(0)
提交回复
热议问题