如何从python的父文件夹导入依赖的cython模块

zyz*_*ler 1 c++ python cython cythonize

想象一下以下文件夹结构:

/project
  run.py
  /Helper
    Helper.pxd
    Helper.pyx
    setup.py
  /Settings
    Settings.pxd
    Settings.pyx
    setup.py
Run Code Online (Sandbox Code Playgroud)

Helper 使用 Settings.pxd 中定义的 Settings 和 PySettings 类型。因此在 Helper.pxd 我正在做:

from Settings cimport Settings, PySettings
Run Code Online (Sandbox Code Playgroud)

在Helper目录下的setup.py中我放

include_path=[".", "../Settings/"]
Run Code Online (Sandbox Code Playgroud)

在 cythonize 命令中。因此 Helper 知道 Settings 并且一切都编译。

在 run.py 中,我想导入 Settings 和 Helper。设置导入工作正常,但在执行时

import Helper.Helper
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Traceback (most recent call last):
  File "run.py", line 1, in <module>
    import Helper.Helper
  File "../Settings/Settings.pxd", line 6, in init Helper
AttributeError: module 'Settings' has no attribute 'PySettings'
Run Code Online (Sandbox Code Playgroud)

一旦所有内容都在同一目录中,此问题就会消失。

为了完整起见,您将在下面找到整个代码:

/项目/运行.py

import Settings.Settings as S
import Helper.Helper as H

settings = S.PySettings()
settings.doSomething()

H.PyMyFunction(settings)
Run Code Online (Sandbox Code Playgroud)

/project/Helper/Helper.pxd

from Settings cimport Settings, PySettings

cdef extern from "../../cppCode/Helper/Helper.h":
  void myFunction(Settings settings)
Run Code Online (Sandbox Code Playgroud)

/project/Helper/Helper.pyx

#distutils: sources = [../../cppCode/Helper/Helper.cpp, ../../cppCode/Settings/Settings.cpp]
#distutils: language = c++

def PyMyFunction(PySettings settings):
  myFunction(settings.c_settings)
Run Code Online (Sandbox Code Playgroud)

/project/Helper/setup.py

from distutils.core import setup
from Cython.Build import cythonize
from setuptools.extension import Extension

extensions = [
  Extension("Helper", ["Helper.pyx"])
]

setup(ext_modules=cythonize(extensions, include_path=[".", "../Settings/"]))
Run Code Online (Sandbox Code Playgroud)

/project/Settings/Settings.pxd

cdef extern from "../../cppCode/Settings/Settings.h":
  cdef cppclass Settings:
    Settings() except +
    void doSomething()

cdef class PySettings:
  cdef Settings c_settings
Run Code Online (Sandbox Code Playgroud)

/project/Settings/Settings.pyx

#distutils: sources = ../../cppCode/Settings/Settings.cpp
#distutils: language = c++

cdef class PySettings:
  def __cinit__(self):
    self.c_settings = Settings()

  def doSomething(self):
    self.c_settings.doSomething()
Run Code Online (Sandbox Code Playgroud)

/项目/设置/setup.py

from distutils.core import setup
from Cython.Build import cythonize
from setuptools.extension import Extension

extensions = [
  Extension("Settings", ["Settings.pyx"])
]

setup(ext_modules=cythonize(extensions))
Run Code Online (Sandbox Code Playgroud)

Dav*_*idW 5

" include_path" 用于 C 包含。它对 Python 在何处查找 pxd 文件没有影响。

您通常需要一个设置文件,位于顶层。更好的方法可能是:

setup.py
project/
  run.py
  __init__.pxd
  Settings/
    __init__.pxd
    Settings.pyx/pxd
  Helper/
    __init__.pxd
    Helper.pyx/pxd
Run Code Online (Sandbox Code Playgroud)

这将创建一个名为“package”的单一模块,该模块将一次性构建并安装。一旦安装,您的用户就可以做到from project import whatever

你会注意到我添加了一些__init__.pxd文件。这些与__init__.py文件的用途基本相同,除了它们将文件夹标识为 Cython 的 cimport 机制的(子)包。

助手 .pxd 然后启动:

from project.Settings.Settings cimport Settings, PySettings
Run Code Online (Sandbox Code Playgroud)

我使用了完整而不是相对导入,因为cimport相对导入似乎有点不可靠。

setup.py 如下:

from setuptools.extension import Extension
from setuptools import setup
from Cython.Build import cythonize

ext_modules = cythonize("project/*/*.pyx")

setup(ext_modules=ext_modules)
Run Code Online (Sandbox Code Playgroud)

欢迎您明确使用,Extension但对于一些简单的事情,将文件模式直接发送到 cythonize 似乎更容易。


我只测试了 Cythonize 阶段,因为我没有编译和运行它所需的 C++ 文件。