在具有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>
这是相关的代码(正在使用的完整代码是here,但是为了简化起见,我删除了在我的构建中被禁用的MPI位和一些VTK日志到终端代码)。
#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()
函数是由绑定包装器逻辑生成的,它看起来像是用于静态构建的(为简洁起见,它已被剪掉):
#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 ++类。
我希望在这种情况下可以使用内置模块,但似乎不行。有没有办法做到这一点?如果不是,那是以前没有必要并且没有人问过的东西,还是明确地不支持它?谢谢。
答案 0 :(得分:0)
似乎一种潜在的解决方案是将所有内置模块放在顶层,而不是放在软件包内部。现在这对我们来说是合适的,因为无论如何我们的编译模块名称都是实现细节,并且我们有蹦床.py
文件来正确确定依赖顺序,以便在派生类型之前正确注册基本类型。我们的修复程序在this MR中进行了描述。