Можно ли использовать статические модули Python во встроенной таблице в качестве подмодулей пакета Python? - PullRequest
0 голосов
/ 21 июня 2019

В статической сборке 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, загружаются первыми.

Я бы ожидал, что встроенные модули будут работать в этом случае, но, похоже, нет. Есть ли способ сделать это? Если нет, то является ли это чем-то, что раньше просто не было необходимо, и никто не спрашивал, или это явно не поддерживается? Спасибо.

1 Ответ

0 голосов
/ 24 июля 2019

Кажется, что одним из возможных решений является размещение всех встроенных модулей на верхнем уровне, а не внутри пакета.Это подходит нам прямо сейчас, потому что имена наших скомпилированных модулей в любом случае являются деталями реализации, и у нас есть файлы trampoline .py, чтобы получить правильный порядок зависимостей, чтобы базовые типы были правильно зарегистрированы перед производными типами.Наше исправление описано в этом MR .

...