繁体   English   中英

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

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

在支持Python的静态VTK构建中,Python模块是静态编译的。 然后将这些模块链接到vtkpython二进制文件中,并在初始化Python解释器之前添加到内置表中。 我们不能使用共享的Python模块,因为这最终会将核心库中的静态全局变量复制到每个共享的Python模块中。

我通过手动添加到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

所以在Python2中不能以这种方式欺骗导入机制。 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>

这是相关的代码( 这里使用的是完整的代码,但是为了简单起见,我已经删除了在我的构建中禁用的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);
}

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.
}

vtkmodules包是Python代码(包括用户实际导入的包装器,确保依赖模块也被导入)。 例如, vtkmodules/vtkCommonDataModel.py如下所示:

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

确保首先加载vtkCommonDataModelPython中使用的C ++类。

我希望在这种情况下做内置模块会起作用,但似乎没有。 有没有办法做到这一点? 如果没有,是否之前没有必要的东西,没有人问过或明确不支持? 谢谢。

似乎一种可能的解决方案是将所有内置模块放在顶层而不是封装内部。 这对我们来说现在很合适,因为我们编译的模块名称无论如何都是实现细节,我们有trampoline .py文件来获得正确的依赖顺序,以便在派生类型之前正确地注册基类型。 我们的修复在此MR中描述。

暂无
暂无

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

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