3
我有问题。我想分发我的cython驱动的包,但我看不到在setup.py中构建它们的简单方法。我想setup.py到:使用cython创建包,以便用户无需安装cython即可安装它
- 最重要的是:安装我的包没有用Cython(从预先生成的C文件或安装用Cython事先)上sdist
- 重建(运行cythonize)封装
- 不需要硬编码我的cython模块列表(只使用glob或其他东西)
- 能够在没有.c文件(不应该存储在git中)或.pyx(可能不分发)的情况下工作。当然,至少有一套这些套将总是存在。 在我痒包
目前,我使用这个相当复杂的代码:
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,
},
)
感谢您的回答!这很容易解决大部分问题。 但是,这需要我分发.pyx文件,以防安装我的软件包的用户安装了Cython。另外,如果我忘记在sdist之前运行build_ext,则创建的程序包将不会保持最新。 – Lefty
一般建议同时发货,是的。另一种方法是需要一个env变量来启用Cython构建,否则默认构建C文件。这将否定必须分发pyx文件。最后一条评论强化了C文件应该回购的原因 - 创建分发应该永远不要依赖于生成不在存储库中的东西。 – danny
如果将USING_CYTHON else {}'添加到您的示例代码中,您可以添加'cmdclass = {'build_ext':build_ext}吗?在此之后,它很好:) (我更喜欢'扩展名(file_name.split('。')[0] .replace(os.path.sep,'。'),sources = [file_name])for file_name在源代码和cythonize导入是不需要的) – Lefty