我正在尝试编写一个Python程序,该程序在运行Python脚本时模拟Py_Main的行为。换句话说,我的行为类似于在命令行中运行python some_file.py
,但是在我的Python脚本中。就我而言,我正在并行编程环境中运行,因此必须在同一个进程中进行声明(这样我才能使用共享内存),所以我不能只使用新的Python解释器。
您可以使用execfile
(or compile
followed by exec
in Python 3)来加载文件本身。但是,通过一些初步测试,我发现execfile
和Py_Main
之间至少有4个区别:
execfile
未正确设置__file__
。默认情况下,它继承父级的全局变量,因此将看到父级的__file__
值。为了解决此问题,您必须为全局变量创建一个新字典并自行设置__file__
。execfile
默认情况下未设置__name__
。您必须自己将其设置为某些内容(例如__main__
)。execfile
根本不会创建新模块。您可以使用imp.new_module()
创建一个新模块来解决此问题,您可以将其用作execfile
的全局范围。execfile
不会创建模块,因此不会将其添加到sys.modules
中。但是,您必须小心执行此操作:例如如果您以__main__
的身份执行顶级脚本,那么sys.modules
可能已经在python top_level.py
中。除了隐藏__main__
的当前值并在之后还原之前,我不确定是否有一种干净的方法。您可以使用其他值,但是那样您就不会遵循与执行脚本相关的常规Python约定。execfile
不会将文件目录添加到sys.path
。结果,您无法从脚本内部import
到同一目录中的另一个模块,而这正是python some_script.py
的工作。这些都不是无法解决的问题,但是我担心这不是一个封闭的问题,如果我走这条路,我将继续发现在解决方案中未正确建模的行为。
我的问题:
有没有一种方法可以在Python中实现,因此可以确保我正确地建模了Py_Main
的所有行为?
如果不这样做,考虑到Python解释器可能已经初始化(即我不能只调用Py_Main
),我至少可以使用C API来做到这一点。例如。 PyRun_SimpleFile
是否具有我想要的行为?从文档来看,这一点都不明显。
或者,在最坏的情况下,至少有关于Py_Main
到底在做什么的文档,以便我可以确定自己在做什么或不愿意花多少钱在Python上模仿? official documentation含糊不清,我通过手动比较execfile
的行为来确定以上所有内容。
编辑:关于runpy
的注释:问了这个问题之后,我发现了runpy.run_path
函数。乍一看,这看起来像我需要的解决方案。但是,它没有解决我上面的第5点。具体来说,在这种情况下,可以观察runpy.run_path("some_dir/test_execfile_helper.py")
和python some_dir/test_execfile_helper.py
之间的区别:
$ cat test_execfile.py
import runpy
runpy.run_path("some_dir/test_execfile_helper.py")
$ cat some_dir/test_execfile_helper.py
print("attempting to import some_other_file")
import some_other_file
$ cat some_dir/some_other_file.py
print("in some_other_file.py")
$ python some_dir/test_execfile_helper.py
attempting to import some_other_file
in some_other_file.py
$ python test_execfile.py
attempting to import some_other_file
Traceback (most recent call last):
File "test_execfile.py", line 2, in <module>
runpy.run_path("some_dir/test_execfile_helper.py")
File "/usr/lib/python2.7/runpy.py", line 252, in run_path
return _run_module_code(code, init_globals, run_name, path_name)
File "/usr/lib/python2.7/runpy.py", line 82, in _run_module_code
mod_name, mod_fname, mod_loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "some_dir/test_execfile_helper.py", line 2, in <module>
import some_other_file
ImportError: No module named some_other_file
因此,也许这是一个比execfile
更好的起点,但我最初的批评仍然存在:我仍然无法知道上面列出的问题清单是否是封闭的。