如何从脚本中执行另一个Python脚本并进行调试?

11 投票
4 回答
8819 浏览
提问于 2025-04-16 03:48

你有一个包装的 Python 脚本,它在调用另一个 Python 脚本,现在是通过 os.system('python another.py some-params') 来实现的。

你希望能够调试这两个脚本,但如果使用 os.system() 的话,你就无法使用调试工具了。因此,直接在同一个解释器中加载第二个脚本,而不是启动一个新的解释器,这样更合理。

使用 import 也不太合适,因为它不会运行 __main__ 部分。

其他方法,比如 exec()runpy,似乎也无法传递 argv 参数。

你觉得有什么解决办法呢?

我在寻找一个解决方案,不需要你修改 another.py 脚本。可能这需要在执行之前修改 sys.argv

4 个回答

2

你能控制一下 another.py 文件吗?如果可以的话,建议你改一下,添加一个 main() 方法。这样的话,你就可以通过 if __name__ == '__main__' 来调用 main()。这样做会大大减轻你遇到的问题。而且,这种方式也方便进行单元测试。

10

到目前为止,我找到的解决方案只适用于Python 2.7及以上版本(runpy.run_path()是在Python 2.7中引入的)。

如果你能找到一个适用于2.6(甚至2.5)的解决方案,欢迎你分享出来。

import runpy, sys
saved_argv = sys.argv
... # patch sys.argv[1:] and load new command line parameters
# run_path() does change only sys.argv[0] but restores it
runpy.run_path('another.py', run_name="__main__")
sys.argv = saved_argv # restore sys.argv
2

根据EOL的建议,我对execfile()做了一个扩展,解决了它的一些限制,叫做execfile2()

下面是代码,不过更新版本会在这里发布。这个扩展与execfile()是兼容的。

def execfile2(filename, _globals=dict(), _locals=dict(), cmd=None, quiet=False):
    _globals['__name__']='__main__'
    saved_argv = sys.argv # we save sys.argv
    if cmd:
    sys.argv=list([filename])
            if isinstance(cmd , list):
                sys.argv.append(cmd)
            else:
                sys.argv.extend(shlex.split(cmd))
    exit_code = 0
try:
        execfile(filename, _globals, _locals)
    except SystemExit as e:
        if isinstance(e.code , int):
            exit_code = e.code # this could be 0 if you do sys.exit(0)
        else:
            exit_code = 1
    except Exception:
        if not quiet:
            import traceback
            traceback.print_exc(file=sys.stderr)
        exit_code = 1
    finally:
        if cmd:
            sys.argv = saved_argv # we restore sys.argv
    return exit_code

撰写回答