首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >用cython创建包,这样用户就可以安装它,而不必安装cython。

用cython创建包,这样用户就可以安装它,而不必安装cython。
EN

Stack Overflow用户
提问于 2017-10-16 23:41:31
回答 1查看 3.1K关注 0票数 10

我有个问题。我想分发我的由cython驱动的包,但我认为在setup.py中构建它们并不容易。我希望setup.py:

  • 最重要的是:在没有cython的情况下安装我的软件包(来自预先生成的C文件或预先安装cython )
  • 在sdist上重新构建(运行cythonize)包
  • 不需要我的cython模块的硬代码列表(只需使用glob或其他什么)
  • 能够在没有.c文件(不应该存储在git中)或.pyx (可能不是分布式的)的情况下工作。当然,其中至少有一套是永远存在的。

目前,在我的“痒包”中,我使用了以下非常复杂的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import os
from glob import glob
from distutils.command.build_ext import build_ext as _build_ext
from distutils.command.sdist import sdist as _sdist
from distutils.core import setup
from distutils.core import Extension



def generate_extensions():
    return [
        # Compile cython-generated .c files into importable .so libraries.
        Extension(os.path.splitext(name)[0], [name])
        for name in C_FILES
    ]


# In distribution version, there are no pyx files, when you clone package from git, there will be no c files.
CYTHON_FILES = glob('itchy/*.pyx')
C_FILES = glob('itchy/*.c')
extensions = generate_extensions()


class build_ext(_build_ext):
    def run(self):
        # Compile cython files (.pyx, some of the .py) into .c files if Cython is available.
        try:
            from Cython.Build import cythonize
            if CYTHON_FILES:
                cythonize(CYTHON_FILES)

                # Update C_FILES in case they were originally missing.
                global C_FILES, extensions
                C_FILES = glob('itchy/*.c')
                extensions = generate_extensions()
            else:
                print('No .pyx files found, building extensions skipped. Pre-built versions will be used.')
        except ImportError:
            print('Cython is not installed, building extensions skipped. Pre-built versions will be used.')
            assert C_FILES, 'C files have to be present in distribution or Cython has to be installed'
        _build_ext.run(self)


class sdist(_sdist):
    def run(self):
        # Make sure the compiled Cython files in the distribution are up-to-date
        self.run_command("build_ext")
        _sdist.run(self)


setup(
    (...)
    ext_modules = extensions,
    cmdclass = {
        'build_ext': build_ext,
        'sdist': sdist,
    },
)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-17 01:53:34

通常通过尝试导入cython并调整扩展到

  1. 如果存在cython,则使用cython构建pyx文件。
  2. 如果cython不存在,则生成C文件

例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try:
    from Cython.Distutils.extension import Extension
    from Cython.Distutils import build_ext
except ImportError:
    from setuptools import Extension
    USING_CYTHON = False
else:
    USING_CYTHON = True

ext = 'pyx' if USING_CYTHON else 'c'
sources = glob('my_module/*.%s' % (ext,))
extensions = [
    Extension(source.split('.')[0].replace(os.path.sep, '.'),
              sources=[source],
    )
for source in sources]
cmdclass = {'build_ext': build_ext} if USING_CYTHON else {}

setup(<..>, ext_modules=extensions, cmdclass=cmdclass)

source.split的内容是必需的,因为source.split扩展名需要以my_module.ext的形式出现,而glob则需要路径名,比如my_module/ext

请参阅此存储库用于一个真实世界的例子。

但是,您应该将.c文件包括在git中以及可发行版中,否则,当需要构建发行版时,.c文件将被重新构建,并且可能与计算机上构建的文件相同,也可能不是。

例如,它们可以由其他版本的cython构建,或者在不同的平台上生成不同的代码。

Cython是一个静态编译器--建议将它生成的文件提交到存储库。

强烈建议您分发生成的.c文件以及您的Cython源代码,这样用户就可以安装您的模块而不需要使用Cython。

请参阅关于分发模块的Cython文档。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46784964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文