Chciałbym stworzyć pakiet Pythona zawierający kod Cythona . Kod Cythona działa dobrze. Jednak teraz chcę wiedzieć, jak najlepiej to zapakować.
Dla większości ludzi, którzy chcą tylko zainstalować pakiet, chciałbym dołączyć .c
plik, który tworzy Cython i zorganizować setup.py
jego kompilację w celu wyprodukowania modułu. Wtedy użytkownik nie potrzebuje zainstalowanego Cythona, aby zainstalować pakiet.
Ale dla osób, które mogą chcieć zmodyfikować pakiet, chciałbym również dostarczyć .pyx
pliki Cython , a także w jakiś sposób umożliwić setup.py
ich zbudowanie przy użyciu Cythona (więc ci użytkownicy musieliby zainstalować Cython).
Jak należy uporządkować pliki w pakiecie, aby zaspokoić oba te scenariusze?
Dokumentacja Cythona zawiera niewielkie wskazówki . Ale nie mówi, jak stworzyć singiel, setup.py
który będzie obsługiwał zarówno sprawy z Cythonem, jak i bez nich.
Odpowiedzi:
Zrobiłem to teraz sam, w pakiecie Pythona
simplerandom
( repozytorium BitBucket - EDIT: teraz github ) (nie spodziewam się, że będzie to popularny pakiet, ale była to dobra okazja, aby nauczyć się Cythona).Ta metoda opiera się na fakcie, że tworzenie
.pyx
pliku w programieCython.Distutils.build_ext
(przynajmniej w wersji Cython 0.14) zawsze wydaje się tworzyć.c
plik w tym samym katalogu, co.pyx
plik źródłowy .Oto skrócona wersja,
setup.py
która, mam nadzieję, pokazuje najważniejsze:Edytowałem również,
MANIFEST.in
aby upewnić się, żemycythonmodule.c
jest uwzględniony w dystrybucji źródłowej (dystrybucji źródłowej utworzonej za pomocąpython setup.py sdist
):Nie zobowiązuję się
mycythonmodule.c
do kontroli wersji „trunk” (lub „default” dla Mercurial). Kiedy robię wydanie, muszę pamiętać o zrobieniupython setup.py build_ext
pierwszego, aby upewnić się, żemycythonmodule.c
jest obecny i aktualny dla dystrybucji kodu źródłowego. Tworzę także gałąź Release i zatwierdzam plik C do gałęzi. W ten sposób mam historyczny zapis pliku C, który był dystrybuowany z tym wydaniem.źródło
Dodając do odpowiedzi Craiga McQueena: zobacz poniżej, jak zastąpić
sdist
polecenie, aby Cython automatycznie kompilował pliki źródłowe przed utworzeniem dystrybucji źródłowej.W ten sposób nie ryzykujesz przypadkowej dystrybucji przestarzałych
C
źródeł. Pomaga również w przypadku, gdy masz ograniczoną kontrolę nad procesem dystrybucji np. Podczas automatycznego tworzenia dystrybucji z ciągłej integracji itp.źródło
http://docs.cython.org/en/latest/src/userguide/source_files_and_compilation.html#distributing-cython-modules
źródło
Najłatwiej jest uwzględnić oba, ale po prostu użyj pliku c? Dołączenie pliku .pyx jest fajne, ale i tak nie jest potrzebne, gdy już masz plik .c. Osoby, które chcą ponownie skompilować .pyx, mogą zainstalować Pyrex i zrobić to ręcznie.
W przeciwnym razie musisz mieć niestandardowe polecenie build_ext dla distutils, które najpierw budują plik C. Cython już zawiera jeden. http://docs.cython.org/src/userguide/source_files_and_compilation.html
To, czego ta dokumentacja nie robi, to powiedzieć, jak uczynić to warunkowym, ale
Powinienem to załatwić.
źródło
setup.py
można było budować bezpośrednio z.pyx
pliku po zainstalowaniu Cythona. Moja odpowiedź również to zaimplementowała.Dołączanie plików .c wygenerowanych przez (Cython) jest dość dziwne. Zwłaszcza jeśli włączymy to do git. Wolałbym użyć setuptools_cython . Gdy Cython nie jest dostępny, zbuduje jajko, które ma wbudowane środowisko Cython, a następnie zbuduje kod za pomocą jajka.
Możliwy przykład: https://github.com/douban/greenify/blob/master/setup.py
Aktualizacja (2017-01-05):
Ponieważ
setuptools 18.0
nie ma potrzeby używaniasetuptools_cython
. Oto przykład zbudowania projektu Cython od zera bezsetuptools_cython
.źródło
'setuptools>=18.0'
setup_requires zamiast tworzenia metodyis_installed
?setuptools>=18.0
został zainstalowany, a następnie wystarczy umieścić'Cython >= 0.18'
wsetup_requires
, i będą instalowane podczas instalacji Cython postępy. Ale jeśli używasz setuptools <18.0, nawet jeśli masz określony cython w setup_requires, nie zostanie on zainstalowany, w tym przypadku powinieneś rozważyć użyciesetuptools_cython
.pip install wheel
. To musi być powód 1. Najpierw zainstaluj koło i spróbuj ponownie.To jest skrypt instalacyjny, który napisałem, który ułatwia dołączanie zagnieżdżonych katalogów do kompilacji. Trzeba go uruchomić z folderu w pakiecie.
Podaj taką strukturę:
setup.py
Miłej kompilacji;)
źródło
Prosty hack, który wymyśliłem:
Po prostu zainstaluj Cython, jeśli nie można go zaimportować. Prawdopodobnie nie powinno się udostępniać tego kodu, ale dla moich własnych zależności jest wystarczająco dobry.
źródło
Wszystkie inne odpowiedzi polegają na
Cython.Build
, co stwarza problem typu kura i jajko między wymaganiem cythonu viasetup_requires
a importem.Nowoczesnym rozwiązaniem jest użycie zamiast tego setuptools, zobacz tę odpowiedź (automatyczna obsługa rozszerzeń Cython wymaga setuptools 18.0, czyli jest dostępna już od wielu lat). Nowoczesny standard
setup.py
z obsługą wymagań, punktem wejścia i modułem cython mógłby wyglądać następująco:źródło
Cython.Build
w czasie konfiguracji powoduje u mnie ImportError. Posiadanie setuptools do skompilowania pyxa to najlepszy sposób na zrobienie tego.Najłatwiejszym sposobem, jaki znalazłem, używając tylko setuptools zamiast ograniczonych funkcji, jest
źródło
Cython.Build
, zobacz moją odpowiedź.Myślę, że znalazłem całkiem dobry sposób na zrobienie tego, udostępniając niestandardowe
build_ext
polecenie. Pomysł jest następujący:Dodaje nagłówki numpy, nadpisując
finalize_options()
i wykonującimport numpy
w treści funkcji, co ładnie unika problemu braku dostępności numpy przedsetup()
jej zainstalowaniem.Jeśli cython jest dostępny w systemie,
check_extensions_list()
podłącza się do metody polecenia i cytonizuje wszystkie nieaktualne moduły cython, zastępując je rozszerzeniami C, które mogą być później obsługiwane przez tębuild_extension()
metodę. Po prostu zapewniamy drugą część funkcjonalności również w naszym module: oznacza to, że jeśli cython nie jest dostępny, ale mamy obecne rozszerzenie C, nadal działa, co pozwala na dystrybucje źródeł.Oto kod:
Pozwala to po prostu napisać
setup()
argumenty bez martwienia się o import i dostępność cythonu:źródło