如何在纯Python中模拟Py_Main

时间:2018-10-20 03:50:02

标签: python python-3.x

我正在尝试编写一个Python程序,该程序在运行Python脚本时模拟Py_Main的行为。换句话说,我的行为类似于在命令行中运行python some_file.py,但是在我的Python脚本中。就我而言,我正在并行编程环境中运行,因此必须在同一个进程中进行声明(这样我才能使用共享内存),所以我不能只使用新的Python解释器。

您可以使用execfileor compile followed by exec in Python 3)来加载文件本身。但是,通过一些初步测试,我发现execfilePy_Main之间至少有4个区别:

  1. execfile未正确设置__file__。默认情况下,它继承父级的全局变量,因此将看到父级的__file__值。为了解决此问题,您必须为全局变量创建一个新字典并自行设置__file__
  2. 类似于上述内容,execfile默认情况下未设置__name__。您必须自己将其设置为某些内容(例如__main__)。
  3. 实际上,execfile根本不会创建新模块。您可以使用imp.new_module()创建一个新模块来解决此问题,您可以将其用作execfile的全局范围。
  4. 由于execfile不会创建模块,因此不会将其添加到sys.modules中。但是,您必须小心执行此操作:例如如果您以__main__的身份执行顶级脚本,那么sys.modules可能已经在python top_level.py中。除了隐藏__main__的当前值并在之后还原之前,我不确定是否有一种干净的方法。您可以使用其他值,但是那样您就不会遵循与执行脚本相关的常规Python约定。
  5. execfile不会将文件目录添加到sys.path。结果,您无法从脚本内部import到同一目录中的另一个模块,而这正是python some_script.py的工作。

这些都不是无法解决的问题,但是我担心这不是一个封闭的问题,如果我走这条路,我将继续发现在解决方案中未正确建模的行为。

我的问题:

  1. 有没有一种方法可以在Python中实现,因此可以确保我正确地建模了Py_Main的所有行为?

  2. 如果不这样做,考虑到Python解释器可能已经初始化(即我不能只调用Py_Main),我至少可以使用C API来做到这一点。例如。 PyRun_SimpleFile是否具有我想要的行为?从文档来看,这一点都不明显。

  3. 或者,在最坏的情况下,至少有关于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更好的起点,但我最初的批评仍然存在:我仍然无法知道上面列出的问题清单是否是封闭的。

0 个答案:

没有答案