簡體   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