如何从python的父文件夹导入依赖的cython模块 [英] How to import depending cython modules from parent folder in python

查看:278
本文介绍了如何从python的父文件夹导入依赖的cython模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Imagine the following folder structure:

/project
  run.py
  /Helper
    Helper.pxd
    Helper.pyx
    setup.py
  /Settings
    Settings.pxd
    Settings.pyx
    setup.py

Helper使用Settings.pxd中定义的Settings和PySettings类型。为此,我正在执行以下操作:

Helper uses the types Settings and PySettings defined in Settings.pxd. Therefor in Helper.pxd I'm doing:

from Settings cimport Settings, PySettings

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

In the setup.py in the Helper directory I put

include_path=[".", "../Settings/"]

cythonize命令。这样,Helper就知道设置和所有编译内容。

in the cythonize command. Thus Helper knows about Settings and everything compiles.

在run.py中,我想导入设置以及Helper。设置导入工作正常,但在执行操作

In run.py I'd like to import Settings as well as Helper. The Settings import works fine but when doing

import Helper.Helper

我收到以下错误:

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'

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

This issue disappears as soon as everything is in the same directory.

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

For the sake of completeness you'll find the whole code below:

/project/run.py

/project/run.py

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

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

H.PyMyFunction(settings)

/ project / Helper / Helper.pxd

/project/Helper/Helper.pxd

from Settings cimport Settings, PySettings

cdef extern from "../../cppCode/Helper/Helper.h":
  void myFunction(Settings settings)

/ project / Helper / Helper.pyx

/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)

/project/Helper/setup.py

/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/"]))

/project/Settings/Settings.pxd

/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

/project/Settings/Settings.pyx

/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()

/project/Settings/setup.py

/project/Settings/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))


推荐答案

include_path 适用于C包含。

您通常希望在顶层使用一个安装文件。更好的方法可能是:

You usually want one setup file, at the top level. A better way of doing it is probably:

setup.py
project/
  run.py
  __init__.pxd
  Settings/
    __init__.pxd
    Settings.pyx/pxd
  Helper/
    __init__.pxd
    Helper.pyx/pxd

这将创建一个名为 package的模块,所有模块都将立即构建并立即安装。安装后,您的用户将可以从项目导入中执行

This will create a single module called "package" which will all be built at once and installed at once. Once installed your user would be able to do from project import whatever.

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

You'll notice I've added some __init__.pxd files. These serve basically the same purpose as __init__.py files, except they identify folders as (sub)packages for Cython's cimport mechanism.

Helper .pxd然后开始:

Helper .pxd then starts:

from project.Settings.Settings cimport Settings, PySettings

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

I've used a full rather than relative import because cimport and relative imports seems a bit unreliable.

Setup.py如下:

Setup.py is as follows:

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

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

setup(ext_modules=ext_modules)

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

You are welcome to explicitly use Extension but for something simple it seemed easier to send the file pattern directly to cythonize.

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

I've only tested the Cythonize stage of this since I don't have the C++ files needed to compile and run it.

这篇关于如何从python的父文件夹导入依赖的cython模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆