В статической сборке VTK с поддержкой Python модули 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 для простоты здесь).
#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 *
, чтобы гарантировать, что классы C ++, используемые в vtkCommonDataModelPython
, загружаются первыми.
Я бы ожидал, что встроенные модули будут работать в этом случае, но, похоже, нет. Есть ли способ сделать это? Если нет, то является ли это чем-то, что раньше просто не было необходимо, и никто не спрашивал, или это явно не поддерживается? Спасибо.