Me gustaría hacer un paquete de Python que contenga algún código de Cython . Tengo el código de Cython funcionando bien. Sin embargo, ahora quiero saber cómo empaquetarlo mejor.
Para la mayoría de las personas que solo desean instalar el paquete, me gustaría incluir el .c
archivo que crea Cython y organizar la setup.py
compilación para producir el módulo. Entonces el usuario no necesita Cython instalado para instalar el paquete.
Pero para las personas que quieran modificar el paquete, me gustaría también como para proporcionar la Cython .pyx
archivos, y de alguna manera también permiten setup.py
construirlos usando Cython (por lo que los usuarios podrían necesitar instalar Cython).
¿Cómo debo estructurar los archivos en el paquete para atender estos dos escenarios?
La documentación de Cython da una pequeña guía . Pero no dice cómo hacer un single setup.py
que maneje ambos casos con / sin Cython.
Respuestas:
Lo hice yo mismo ahora, en un paquete de Python
simplerandom
( BitBucket repo - EDIT: ahora github ) (no espero que sea un paquete popular, pero fue una buena oportunidad para aprender Cython).Este método se basa en el hecho de que construir un
.pyx
archivo conCython.Distutils.build_ext
(al menos con la versión 0.14 de Cython) siempre parece crear un.c
archivo en el mismo directorio que el.pyx
archivo fuente .Aquí hay una versión reducida de la
setup.py
que espero muestre lo esencial:También edité
MANIFEST.in
para asegurarme de quemycythonmodule.c
esté incluido en una distribución fuente (una distribución fuente que se crea conpython setup.py sdist
):No me comprometo
mycythonmodule.c
con el control de versiones 'trunk' (o 'default' para Mercurial). Cuando hago un lanzamiento, necesito recordar hacerpython setup.py build_ext
primero, para asegurarme de quemycythonmodule.c
esté presente y actualizado para la distribución del código fuente. También hago una rama de lanzamiento y confirmo el archivo C en la rama. De esa manera tengo un registro histórico del archivo C que se distribuyó con esa versión.fuente
Agregando a la respuesta de Craig McQueen: vea a continuación cómo anular el
sdist
comando para que Cython compile automáticamente sus archivos fuente antes de crear una distribución fuente.De esta forma, no corre el riesgo de distribuir accidentalmente
C
fuentes obsoletas . También ayuda en el caso de que tenga un control limitado sobre el proceso de distribución, por ejemplo, al crear distribuciones automáticamente a partir de la integración continua, etc.fuente
http://docs.cython.org/en/latest/src/userguide/source_files_and_compilation.html#distributing-cython-modules
fuente
¿Lo más fácil es incluir ambos pero solo usar el archivo c? Incluir el archivo .pyx es bueno, pero no es necesario una vez que tenga el archivo .c de todos modos. Las personas que desean recompilar el .pyx pueden instalar Pyrex y hacerlo manualmente.
De lo contrario, debe tener un comando personalizado build_ext para distutils que primero compila el archivo C. Cython ya incluye uno. http://docs.cython.org/src/userguide/source_files_and_compilation.html
Lo que no hace esa documentación es decir cómo hacer que esto sea condicional, pero
Debería manejarlo.
fuente
setup.py
pueda construir directamente desde el.pyx
archivo cuando se instala Cython. Mi respuesta también lo ha implementado.Incluyendo (Cython) los archivos .c generados son bastante raros. Especialmente cuando incluimos eso en git. Prefiero usar setuptools_cython . Cuando Cython no está disponible, creará un huevo que tiene un entorno Cython incorporado, y luego construirá su código usando el huevo.
Un posible ejemplo: https://github.com/douban/greenify/blob/master/setup.py
Actualización (2017-01-05):
Desde entonces
setuptools 18.0
, no hay necesidad de usarsetuptools_cython
. Aquí hay un ejemplo para construir un proyecto Cython desde cero sin élsetuptools_cython
.fuente
'setuptools>=18.0'
setup_requires en lugar de crear el métodois_installed
?setuptools>=18.0
se ha instalado, a continuación, sólo tiene que poner'Cython >= 0.18'
ensetup_requires
, y Cython se instalará durante la instalación progreso. Pero si está utilizando setuptools <18.0, incluso su cython específico en setup_requires, no se instalará, en este caso, debe considerar su usosetuptools_cython
.pip install wheel
. Entonces debe ser la razón 1. Instale la rueda primero e intente nuevamente.Este es un script de configuración que escribí que hace que sea más fácil incluir directorios anidados dentro de la compilación. Uno necesita ejecutarlo desde la carpeta dentro de un paquete.
Estructura Givig como esta:
setup.py
Compilación feliz;)
fuente
El simple truco que se me ocurrió:
Simplemente instale Cython si no se pudo importar. Probablemente no se deba compartir este código, pero para mis propias dependencias es lo suficientemente bueno.
fuente
Todas las demás respuestas dependen de
Cython.Build
, lo que crea un problema de huevo y gallina entre requerir cython víasetup_requires
e importarlo.Una solución moderna es usar setuptools en su lugar, vea esta respuesta (el manejo automático de extensiones de Cython requiere setuptools 18.0, es decir, está disponible desde hace muchos años). Un estándar moderno
setup.py
con manejo de requisitos, un punto de entrada y un módulo cython podría verse así:fuente
Cython.Build
el momento de la configuración me causa ImportError. Tener herramientas de configuración para compilar pyx es la mejor manera de hacerlo.La forma más fácil que encontré usando solo herramientas de configuración en lugar de la característica limitada distutils es
fuente
Cython.Build
, vea mi respuesta.Creo que encontré una forma bastante buena de hacerlo proporcionando un
build_ext
comando personalizado . La idea es la siguiente:Agrego los encabezados numpy anulando
finalize_options()
y haciendoimport numpy
en el cuerpo de la función, lo que evita muy bien el problema de que numpy no esté disponible antes desetup()
instalarlo.Si cython está disponible en el sistema, se engancha en el
check_extensions_list()
método del comando y por cythoniza todos los módulos de cython desactualizados, reemplazándolos con extensiones C que luego puede manejar elbuild_extension()
método. También proporcionamos la última parte de la funcionalidad en nuestro módulo: esto significa que si cython no está disponible pero tenemos una extensión C presente, todavía funciona, lo que le permite hacer distribuciones de origen.Aquí está el código:
Esto le permite a uno escribir los
setup()
argumentos sin preocuparse por las importaciones y si uno tiene cython disponible:fuente