带有 cython 扩展名的“python setup.py sdist”:.pyx”与任何文件都不匹配

KAI*_*HAO 5 python pip setuptools cython

我正在维护一个 python 包,其中包含基于 cython 的 c 扩展。源代码在github上:https: //github.com/vlkit/vlkit

这是我的setup.py

import os
from setuptools import setup, find_packages
from distutils.core import Extension

try:
    import numpy
except ImportError:  # We do not have numpy installed
    os.system("pip install numpy")

try:
    from Cython.Build import cythonize
except ImportError:  # We do not have Cython installed
    os.system("pip install Cython")

import numpy
from Cython.Build import cythonize

__version__ = "0.1.0-b3"

exts = [Extension(name='vltools.nms.nms_ext',
                  sources=["vltools/nms/nms_ext.pyx"],
                  include_dirs=[numpy.get_include()])
        ]

setup(name='vltools',
  version=__version__,
  description='vision and learning tools',
  url='https://github.com/vltools/vltools',
  author_email='a@b.c',
  license='MIT',
  packages=find_packages(),
  ext_modules=cythonize(exts),
  zip_safe=False,
  data_files=[("data", ["data/imagenet1000_clsidx_to_labels.txt"])]
)
Run Code Online (Sandbox Code Playgroud)

当使用 进行本地构建时python setup build && python setup.py install,一切都会顺利进行。

但是,当我尝试创建源发行版,然后python setup.py sdist从生成的版本安装时,dist/vltools-0.1.0b3.tar.gz会遇到错误:

ValueError: 'vltools/nms/nms_ext.pyx' doesn't match any files
Run Code Online (Sandbox Code Playgroud)

根据我的理解,安装实际需要的nms_ext.c实际上是在生成的dist/vltools-0.1.0b3.tar.gz.

但是,在我的 setup.py 中,源代码中是“nms_ext.pyx”:

exts = [Extension(name='vltools.nms.nms_ext',
                  sources=["vltools/nms/nms_ext.pyx"],
                  include_dirs=[numpy.get_include()])
        ]
Run Code Online (Sandbox Code Playgroud)

那么,在使用 来创建源代码发行版时我应该做什么python setup.py sdist

hoe*_*ing 3

设置脚本中有几处需要修复或改进。

声明构建和运行时依赖项

声明依赖关系的正确方法是将它们传递到/ args中pip install {numpy,cython},而不是在很多事情可能出错的地方运行。Cython 仅在构建阶段需要,但在安装和导入时不需要 - 它将被添加到. 构建和运行该包都是必需的,因此它包含在两个列表中:setup()setup_requiresinstall_requiresvltoolssetup_requiresnumpy

setup(
    ...,
    setup_requires=["cython", "numpy"],
    install_requires=["numpy"],
)
Run Code Online (Sandbox Code Playgroud)

这样做的好处是不会安装 Cython。它将被下载、用于构建然后被删除。

您可以(并且应该)install_requires使用其他软件包vltools需求来扩展列表,例如scipypillow等等。

推迟 Cython 和 numpy 导入

为了确保该包可以安装在既没有 Cython 也没有事先安装的系统上numpy,我们必须推迟它们的导入。我不会在这里详细介绍;查看Add numpy.get_include() argument to setuptools without preinstalled numpy了解更多详细信息。在下面命令的自定义实现中build,我使用 include 推迟了 cythonizing 和扩展扩展标头numpy

class build(build_orig):

    def finalize_options(self):
        super().finalize_options()
        __builtins__.__NUMPY_SETUP__ = False
        import numpy
        for extension in self.distribution.ext_modules:
            extension.include_dirs.append(numpy.get_include())
        from Cython.Build import cythonize
        self.distribution.ext_modules = cythonize(self.distribution.ext_modules,
                                                  language_level=3)
Run Code Online (Sandbox Code Playgroud)

通过以下方式注册自定义命令 impl cmdclass

setup(
    ...,
    cmdclass={"build": build},
)
Run Code Online (Sandbox Code Playgroud)

包装nms.h

目前,nms.h尚未将其添加到您的源目录中,因此无法进行安装。通过将其包括在内,可以轻松解决此问题,例如package_data

setup(
    ...,
    package_data={"vltools.nms": ["nms.h"]},
)
Run Code Online (Sandbox Code Playgroud)

nms.h现在您还应该添加to的父目录include_dirs

exts = [Extension(name='vltools.nms.nms_ext',
                  sources=["vltools/nms/_nms_ext.c", "vltools/nms/nms_ext.pyx"],
                  include_dirs=["vltools/nms"])]
Run Code Online (Sandbox Code Playgroud)

完整的设置脚本

import os
from setuptools import setup, find_packages
from setuptools import Extension
from distutils.command.build import build as build_orig

__version__ = "0.1.0b3"

exts = [Extension(name='vltools.nms.nms_ext',
                  sources=["vltools/nms/_nms_ext.c", "vltools/nms/nms_ext.pyx"],
                  include_dirs=["vltools/nms"])]


class build(build_orig):

    def finalize_options(self):
        super().finalize_options()
        __builtins__.__NUMPY_SETUP__ = False
        import numpy
        for extension in self.distribution.ext_modules:
            extension.include_dirs.append(numpy.get_include())
        from Cython.Build import cythonize
        self.distribution.ext_modules = cythonize(self.distribution.ext_modules,
                                                  language_level=3)


setup(name='vltools',
    version=__version__,
    description='vision and learning tools',
    url='https://github.com/vltools/vltools',
    author_email='kz@kaizhao.net',
    license='MIT',
    packages=find_packages(),
    ext_modules=exts,
    setup_requires=["cython", "numpy"],
    install_requires=["numpy"],
    zip_safe=False,
    data_files=[("data", ["data/imagenet1000_clsidx_to_labels.txt"])],
    package_data={"vltools.nms": ["nms.h"]},
    cmdclass={"build": build},
)
Run Code Online (Sandbox Code Playgroud)

PS两年过去了,我们又见面了;-)