bar.py 必须像 Python 解释器本身一样运行 foo.py(或 foo.pyc,正如您所要求的那样),就好像它是主脚本一样。这出乎意料地难。我 90% 的解决方案是这样的:
def run_script_as_main(cmdline):
# It is crucial to import locally what we need as we
# later remove everything from __main__
import sys, imp, traceback, os
# Patch sys.argv
sys.argv = cmdline
# Clear the __main__ namespace and set it up to run
# the secondary program
maindict = sys.modules["__main__"].__dict__
builtins = maindict['__builtins__']
maindict.clear()
maindict['__file__'] = cmdline[0]
maindict['__builtins__'] = builtins
maindict['__name__'] = "__main__"
maindict['__doc__'] = None
# Python prepends a script's location to sys.path
sys.path[0] = os.path.dirname(os.path.abspath(cmdline[0]))
# Treat everything as a Python source file, except it
# ends in '.pyc'
loader = imp.load_source
if maindict["__file__"].endswith(".pyc"):
loader = imp.load_compiled
with open(cmdline[0], 'rb') as f:
try:
loader('__main__', maindict["__file__"], f)
except Exception:
# In case of an exception, remove this script from the
# stack trace; if you don't care seeing some bar.py in
# traceback, you can leave that out.
ex_type, ex_value, ex_traceback = sys.exc_info()
tb = traceback.extract_tb(ex_traceback, None)[1:]
sys.stderr.write("Traceback (most recent call last):\n")
for line in traceback.format_list(tb):
sys.stderr.write(line)
for line in traceback.format_exception_only(ex_type, ex_value):
sys.stderr.write(line)
这模仿了 Python 解释器的默认行为
比较密切。它设置系统全局变量__name__、__file__、
sys.argv,将脚本位置插入sys.path,清除全局命名空间等。
您可以将该代码复制到 bar.py 或从某处导入并像这样使用它:
if __name__ == "__main__":
# You debugging setup goes here
...
# Run the Python program given as argv[1]
run_script_as_main(sys.argv[1:])
那么,鉴于此:
$ find so-foo-bar
so-foo-bar
so-foo-bar/debugaid
so-foo-bar/debugaid/bar.py
so-foo-bar/foo.py
和foo.py 看起来像这样:
import sys
if __name__ == "__main__":
print "My name is", __name__
print "My file is", __file__
print "My command line is", sys.argv
print "First 2 path items", sys.path[:2]
print "Globals", globals().keys()
raise Exception("foo")
...通过bar.py 运行foo.py 会为您提供:
$ python so-foo-bar/debugaid/bar.py so-foo-bar/foo.py
我的名字是__main__
我的文件是 so-foo-bar/foo.py
我的命令行是 ['so-foo-bar/foo.py']
前 2 个路径项 ['~/so-foo-bar', '/usr/local/...']
全局变量 ['__builtins__', '__name__', '__file__', 'sys', '__package__', '__doc__']
回溯(最近一次通话最后):
文件“so-foo-bar/foo.py”,第 9 行,在
引发异常(“foo”)
例外:foo
虽然我猜run_script_as_main 缺少一些有趣的细节,但它与 Python 运行 foo.py 的方式非常接近。