Ich habe eine Frage. Ich möchte meine Cython-basierten Pakete verteilen, aber ich sehe keine einfache Möglichkeit, sie in setup.py zu erstellen. Ich möchte setup.py zu:Erstellen Sie ein Paket mit Cython, damit Benutzer es installieren können, ohne Cython bereits installiert zu haben
- was am wichtigsten ist: mein Paket ohne cython (aus der vorab generierten C-Dateien oder durch vorher Installation cython) installieren
- Wiederaufbau (run cythonize) Paket auf Sdist
- nicht Ich muss eine Liste meiner Cython-Module hartcodieren (verwende einfach glob oder sowas)
- kann ohne .c-Dateien arbeiten (sollte nicht in git gespeichert werden) oder .pyx (kann nicht verteilt werden). Mindestens einer dieser Sätze wird natürlich immer vorhanden sein.
Zeit in meinem juckenden Paket, verwende ich diesen ziemlich komplizierten Code:
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,
},
)
Danke für die Antwort! Dies löst die meisten Probleme recht einfach. Allerdings müsste ich .pyx-Dateien nur dann verteilen, wenn der Benutzer, der mein Paket installiert, Cython bereits installiert hat. Auch wenn ich vergessen hätte, build_ext vor sdist auszuführen, wäre das erstellte Paket nicht auf dem neuesten Stand. – Lefty
Es wird generell empfohlen, beides zu versenden, ja. Ein anderer Ansatz wäre, eine env-Variable zu benötigen, um das Erstellen mit Cython zu ermöglichen, und andernfalls das Erstellen von C-Dateien. Das würde es unnötig machen, pyx-Dateien zu verteilen.Der letzte Kommentar bekräftigt, warum C-Dateien im Repo sein sollten - das Erstellen einer Distribution sollte niemals davon abhängen, etwas erzeugen zu müssen, das nicht im Repository ist. – danny
Können Sie 'cmdclass = {'build_ext': build_ext} wenn USING_CYTHON else {}' zu Ihrem Beispielcode hinzufügen? Danach funktioniert es gut :) (auch ich bevorzuge 'Extension (file_name.split ('.') [0] .replace (os.path.sep, '.'), Sources = [file_name]) für file_name in Quellen und cythonize Import ist nicht erforderlich) – Lefty