6

假设您有一个包含 Python 脚本路径的字符串,并且您希望以透明的方式加载和执行该脚本(因此内部脚本与直接通过“python 路径”运行相比没有根本区别)。然后得到生成的全局字典。我认为 runpy.run_path() 可以做到这一点,但有两个问题。如果路径包含一些 unicode 字符,则它不起作用(请参阅http://bugs.python.org/issue17588)。最重要的是,给定全局字典只是原始字典的副本,因为当临时模块对象被垃圾收集时,这个原始字典会被清除。所以一个函数对象已经损坏了 __globals__ dict(参见http://bugs.python.org/issue18331)。

您对如何运行内部脚本有任何想法吗?

更新:查看我目前的方法 - http://bpaste.net/show/RzAbQxLNXiJsXYm2fplz/。有什么建议么?改进?例如,从正在运行的脚本的角度来看,可能会有所不同的细节。我知道重新加载 __main__ 的问题。

4

1 回答 1

1

导入模块会在顶层执行代码,并且该模块的“全局”命名空间被导入为模块的名称

james@bodacious:~$cat test.py
def func():
  pass

myname = "michael caine"

print "hello, %s" % myname
james@bodacious:~$python
Python 2.7.5 (default, Jul 12 2013, 18:42:21)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
hello, michael caine
>>> dir(test)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'func', 'myname']
>>>

如果您要运行的代码位于文件的顶层,只需导入模块即可执行代码让您在一个方便的包中访问其“全局”命名空间。如果您要运行的代码不在顶层(例如,如果它在一个main()只能通过常用if __name__=="__main__"技巧触发的函数中),您可以自己调用该函数:

james@bodacious:~$cat test.py

def main():
    print "hello there!"

if __name__=="__main__":
    main()
james@bodacious:~$python
Python 2.7.5 (default, Jul 12 2013, 18:42:21)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> test.main()
hello there!
>>>

当然,您要导入的文件可能不在 sys.path 中,因此不能简单地使用import. 一个简单的解决方案可能是操作sys.path,但是如何在给定完整路径的情况下导入模块?描述使用更好的解决方案imp.load_source()

于 2013-07-31T22:29:33.913 回答