2015-05-10 35 views
7

Ten setup.py:Collapse wiele Submoduły do ​​jednego rozszerzenia Cython

from distutils.core import setup 
from distutils.extension import Extension 
from Cython.Build import cythonize 

extensions = (
    Extension('myext', ['myext/__init__.py', 
         'myext/algorithms/__init__.py', 
         'myext/algorithms/dumb.py', 
         'myext/algorithms/combine.py']) 
) 
setup(
    name='myext', 
    ext_modules=cythonize(extensions) 
) 

nie ma zamierzony efekt. Chcę, żeby wyprodukował pojedynczy myext.so, który robi; ale kiedy powoływać go poprzez

python -m myext.so 

uzyskać:

ValueError: Attempted relative import in non-package 

ze względu na fakt, że myext próby skierowania do .algorithms.

Każdy pomysł, jak to działa?

+0

Czy ten przewodnik w ogóle Ci pomaga? https://github.com/cython/cython/wiki/PackageHierarchy –

+0

Tak naprawdę czytałem i śledziłem to; Problem polega na tym, że nie mają jednego wyjścia binarnego. Produkują plik binarny dla każdego pliku Pythona. – Reinderien

Odpowiedz

4

Po pierwsze, powinienem zauważyć, że jest to impossible, aby skompilować pojedynczy plik .so z pakietami podrzędnymi za pomocą Cython. Więc jeśli chcesz pakiety podrzędne, będziesz musiał wygenerować wiele plików .so, ponieważ każdy .so może reprezentować tylko jeden moduł.

Po drugie, wygląda na to, że nie można skompilować wielu plików Cython/Python (w szczególności używam języka Cython) i połączyć je w pojedynczy moduł.

Próbowałem skompilować pomnożyć pliki Cython w pojedynczy .so w każdy sposób, zarówno z distutils i kompilacji ręcznej, i zawsze nie można importować w czasie wykonywania.

Wydaje się, że wystarczy połączyć skompilowany plik Cythona z innymi bibliotekami, a nawet z innymi plikami C, ale coś idzie nie tak podczas łączenia dwóch skompilowanych plików Cythona, a wynik nie jest poprawnym rozszerzeniem Pythona.

Jedyne rozwiązanie, które mogę zobaczyć, to skompilowanie wszystkiego jako pojedynczego pliku Cythona. W moim przypadku, mam edytowane mój setup.py wygenerować pojedynczy .pyx plik, który z kolei include ów każdy plik .pyx w moim katalogu źródłowego:

includesContents = "" 
for f in os.listdir("src-dir"): 
    if f.endswith(".pyx"): 
     includesContents += "include \"" + f + "\"\n" 

includesFile = open("src/extension-name.pyx", "w") 
includesFile.write(includesContents) 
includesFile.close() 

Potem wystarczy skompilować extension-name.pyx. Oczywiście powoduje to narastającą przyrostową i równoległą kompilację, a możesz skończyć z dodatkowymi konfliktami nazw, ponieważ wszystko zostanie wklejone do tego samego pliku. Z drugiej strony nie musisz pisać żadnych plików .pyd.

Z pewnością nie nazwałbym tego preferowaną metodą kompilacji, ale jeśli wszystko musi koniecznie znajdować się w jednym module rozszerzeń, jest to jedyny sposób, w jaki mogę to zrobić.