简体   繁体   English

是否可以在内置表中使用静态Python模块作为Python包的子模块?

[英]Is it possible to use static Python modules in the builtin table as submodules of a Python package?

In a static VTK build with Python support, the Python modules are compiled statically. 在支持Python的静态VTK构建中,Python模块是静态编译的。 These modules are then linked into the vtkpython binary and added to the builtin table prior to the Python interpreter being initialized. 然后将这些模块链接到vtkpython二进制文件中,并在初始化Python解释器之前添加到内置表中。 We cannot use shared Python modules because that would end up duplicating static globals from the core libraries into each of the shared Python modules. 我们不能使用共享的Python模块,因为这最终会将核心库中的静态全局变量复制到每个共享的Python模块中。

I've tried "tricking" the import machinery by adding to sys.modules manually: 我通过手动添加到sys.modules尝试“欺骗”导入机制:

Python 2.7.16 (default, Apr 30 2019, 15:54:59) 
[GCC 8.3.1 20190223 (Red Hat 8.3.1-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import math
>>> sys.modules['vtkmodules.vtkCommonCorePython'] = math
>>> import vtkmodules.vtkCommonCorePython
>>> import vtkmodules
>>> from vtkmodules import vtkCommonCorePython
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name vtkCommonCorePython

so the import mechanisms cannot be tricked in this way in Python2. 所以在Python2中不能以这种方式欺骗导入机制。 There might be some hope for Python3 that such a hack would work: Python3可能有一些希望,这样的黑客可以工作:

% bin/vtkpython
Python 3.7.3 (default, May 11 2019, 00:45:16) 
[GCC 8.3.1 20190223 (Red Hat 8.3.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import math
>>> sys.modules['vtkmodules.vtkCommonCorePython'] = math
>>> from vtkmodules import vtkCommonCorePython
>>> vtkCommonCorePython.sin
<built-in function sin>

Here's the relevant code (full code in use is here , but I've stripped out MPI bits which are disabled in my build and some VTK log-to-terminal code for simplicity here). 这是相关的代码( 这里使用的是完整的代码,但是为了简单起见,我已经删除了在我的构建中禁用的MPI位和一些VTK log-to-terminal代码)。

#include "vtkPython.h"
#include "vtkPythonCompatibility.h"

#include "vtkPythonInterpreter.h"
#include "vtkpythonmodules.h"
#include <vtksys/SystemTools.hxx>
// SNIP: some headers removed for brevity.

#include <string>

int main(int argc, char **argv)
{
  std::string fullpath;
  std::string error;

  if (vtksys::SystemTools::FindProgramPath(argv[0], fullpath, error))
  {
    vtkPythonInterpreter::SetProgramName(fullpath.c_str());
  }

  // SNIP: MPI setup (associated class also removed above)

  /**
   * This function is generated and exposed in vtkpythonmodules.h.
   * This registers any Python modules for VTK for static builds.
   */
  vtkpythonmodules_load();

  // SNIP: VTK log-to-terminal logic

  return vtkPythonInterpreter::PyMain(argc, argv);
}

The vtkpythonmodules_load() function is generated by the bindings wrapper logic and looks like this for a static build (snipped for brevity): vtkpythonmodules_load()函数由绑定包装器逻辑生成,对于静态构建看起来像这样(为简洁而vtkpythonmodules_load() ):

#include "vtkCommonCorePython.h"
// SNIP: Includes for other Python init functions.
#if PY_VERSION_HEX < 0x03000000         
#define PY_IMPORT(module) PyImport_AppendInittab("vtkmodules." #module, init ## module)            
#else                                     
#define PY_IMPORT(module) PyImport_AppendInittab("vtkmodules." #module, PyInit_ ## module)         
#endif                                

static void vtkpythonmodules_load() {     
  PY_IMPORT(vtkCommonCorePython);
  // SNIP: PY_IMPORT calls for the rest of VTK's modules.
}

The vtkmodules package is otherwise Python code (including wrappers for users to actually import which ensure that dependent modules are also imported). vtkmodules包是Python代码(包括用户实际导入的包装器,确保依赖模块也被导入)。 For example, vtkmodules/vtkCommonDataModel.py looks like this: 例如, vtkmodules/vtkCommonDataModel.py如下所示:

from __future__ import absolute_import
from . import vtkCommonCore
from . import vtkCommonMath
from . import vtkCommonTransforms
from .vtkCommonDataModelPython import *

to ensure that the C++ classes used by those in vtkCommonDataModelPython are loaded first. 确保首先加载vtkCommonDataModelPython中使用的C ++类。

I'd expect that doing builtin modules would work in this case, but it seems not. 我希望在这种情况下做内置模块会起作用,但似乎没有。 Is there a way to do this? 有没有办法做到这一点? If not, is it something that just hasn't been necessary before and no one has asked or is it explicitly not supported? 如果没有,是否之前没有必要的东西,没有人问过或明确不支持? Thanks. 谢谢。

It seems that one potential solution is to place all of the builtin modules at the top-level rather than inside of a package. 似乎一种可能的解决方案是将所有内置模块放在顶层而不是封装内部。 This is suitable for us right now because our compiled module names are implementation details anyways and we have the trampoline .py files to get dependency order correct so that base types are properly registered before derived types. 这对我们来说现在很合适,因为我们编译的模块名称无论如何都是实现细节,我们有trampoline .py文件来获得正确的依赖顺序,以便在派生类型之前正确地注册基类型。 Our fix is described in this MR . 我们的修复在此MR中描述。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM