如何从脚本中执行另一个Python脚本并进行调试?
你有一个包装的 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