使用Setuptools中的Cythonize构建和交付Python模块

时间:2019-11-22 10:46:27

标签: python cython setuptools cythonize

使用Cython和cythonize编译后,我正在构建一个Python包。

以下是我的 setup.py 外观的示例:

from setuptools import setup, find_packages, Extension
from Cython.Build import cythonize


setup(
    name="My_Pkg",
    version="0.0",
    ext_modules=cythonize('lib/my_pkg/my_mod.py'),
)

以下是我的项目目录树的示例:

.
├── lib
│   └── my_pkg
│       ├── __init__.py
│       └── my_mod.py
└── setup.py

执行setuptools时,一切正常:

MACOSX_DEPLOYMENT_TARGET=10.15.1 python setup.py build_ext bdist_wheel

我的模块已正确转换为“ .c”,并在“ build”目录中编译为“ .so”。完成所有操作后,将在'dist'中创建wheel:

.
├── My_Pkg.egg-info
│   ├── PKG-INFO
│   ├── SOURCES.txt
│   ├── dependency_links.txt
│   └── top_level.txt
├── build
│   ├── bdist.macosx-10.7-x86_64
│   ├── lib.macosx-10.7-x86_64-3.7
│   │   └── my_pkg
│   │       └── my_mod.cpython-37m-darwin.so
│   └── temp.macosx-10.7-x86_64-3.7
│       └── lib
│           └── my_pkg
│               └── my_mod.o
├── dist
│   └── My_Pkg-0.0-cp37-cp37m-macosx_10_7_x86_64.whl
├── lib
│   └── my_pkg
│       ├── __init__.py
│       ├── my_mod.c
│       └── my_mod.py
└── setup.py

我的问题是我想在setuptools构建阶段将'__init__.py'也复制到'build'中(而不进行编译)。我也希望将其包装在生成的轮子中,作为发行版的一部分。

有什么主意吗?

2 个答案:

答案 0 :(得分:1)

要使其正常工作,我必须在setup中的setup.py上添加两个关键字参数:

packages=["my_pkg"],
package_dir={'': 'lib'},do two things:

(您可能还可以使用find_packages。这是告诉setuptools应该安装的Python软件包的方法。特别是告诉我们,我们有一个名为“ my_pkg”的软件包,它应该在{{ 1}},这是他们最好的阅读is the distutils documentation的地方(setuptools建立在distutils上,但主要记录了更改)。

请注意,这不包括“ build”文件夹中的.py文件。这纯粹是一个临时的工作空间,因此毫无意义地将文件无意义地复制到其中。您不应该尝试导入保存在“ build”文件夹中的模块,它们包含在车轮中,这是能够分发它们的重要点。

答案 1 :(得分:0)

感谢帮助表单的注释,this other post我提出了使用以下“ setup.py”的解决方案:

from setuptools import setup
from setuptools.command.build_py import build_py as build_py_orig
from Cython.Build import cythonize


class build_py(build_py_orig):

    def find_package_modules(self, package, package_dir):
        modules = super().find_package_modules(package, package_dir)
        return [(pkg, mod, file, ) for (pkg, mod, file, ) in modules if mod == '__init__']


setup(
    name="My_Pkg",
    version="0.0",
    ext_modules=cythonize('lib/my_pkg/my_mod.py'),
    packages=["my_pkg"],
    package_dir={'': 'lib'},
    cmdclass={'build_py': build_py},
)