首页 > 解决方案 > 设置 setuptools 以创建带有可用标头的 cimportable 包

问题描述

我尝试实现答案https://stackoverflow.com/a/57480599/7482208,但我坚持从另一个包导入一个包。

代码在这里:https ://github.com/iamishalkin/setuptools_cython_question

我想要的是wrap从 wrapper 文件夹中获得一个独立的包,这样您就可以在没有cust包的情况下使用它。

而且我还希望能够通过FuncWrapperwrap.

我所做的:

所以问题是:如何将.pxd文件添加到最终包中。

我也试过sdist不编​​译 cython 代码而只是复制它。

标签: pythoncythonsetuptoolscimport

解决方案


As I said in a comment, the Cython documentation recommends putting .pxd files in package_data to install them. This necessitates a slightly different structure:

| setup.py
+ wrapper
   | wrap.pxd
   | wrap.pyx
   | __init__.py # just so it's recognised as a package
                 # may be unnecessary with recent Python versions

setup.py then creates a "package" called wrapper (this is modified from your version so it's possible it could be simplied further):

from setuptools import setup, Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext

NAME = "some_name"

ext_abc = Extension(name="wrapper.wrap",
                    sources=["wrapper/wrap.pyx"]
                    )

EXTENSIONS = [
    ext_abc
]

if __name__ == "__main__":
    setup(
        zip_safe=False,
        name=NAME,
        packages=["wrapper"],
        cmdclass={"build_ext": build_ext},
        ext_modules=cythonize(EXTENSIONS, language_level=3),
        package_data = {
            "wrapper": ["*.pxd"],
    },
        )

Note that I've changed the name of the extension to "wrapper.wrap" to ensure that it's installed as part of the package. The package_data is then able to recognised .pxd files as part of wrapper that you want to install. This doesn't work unless you put it in a "package".

You then install it. I just installed it with python3 setup.py install but I'm sure going through a wheel does largely the same thing.


For another module to use you file it's very simple:

from wrapper.wrap cimport FuncWrapper

The setup.py for that other module need have nothing special - you definitely don't need anything like include_dirs=wrap.get_include().

If you want to have an interface where you don't need submodules so can just do

from wrapper cimport FuncWrapper

then just use an __init__.py containing:

from .wrap import *

and an __init__.pxd containing:

from wrapper.wrap cimport * # relative import is a little broken in Cython I think

I'm sure there are other ways of doing this - I've only really used setuptools for compiling Cython stuff and never really worried about distributing too much so am not an expert - but this looks to be the standard approach.


推荐阅读