Eu gostaria de fazer um pacote Python contendo algum código Cython . Eu tenho o código Cython funcionando bem. No entanto, agora eu quero saber a melhor forma de empacotá-lo.
Para a maioria das pessoas que apenas deseja instalar o pacote, gostaria de incluir o .c
arquivo que o Cython cria e providenciar setup.py
a compilação para produzir o módulo. Em seguida, o usuário não precisa do Cython instalado para instalar o pacote.
Mas para as pessoas que podem querer modificar o pacote, eu também gostaria de fornecer os Cython .pyx
arquivos, e de alguma forma também permitem setup.py
para construí-los usando Cython (para aqueles usuários que precisam Cython instalado).
Como devo estruturar os arquivos no pacote para atender a esses dois cenários?
A documentação do Cython fornece um pouco de orientação . Mas não diz como criar um single setup.py
que lide com os casos com / sem Cython.
Respostas:
Eu já fiz isso agora, em um pacote Python
simplerandom
( repositório BitBucket - EDIT: agora github ) (não espero que seja um pacote popular, mas foi uma boa chance de aprender Cython).Este método baseia-se no fato de que a criação de um
.pyx
arquivo comCython.Distutils.build_ext
(pelo menos com o Cython versão 0.14) sempre parece criar um.c
arquivo no mesmo diretório que o.pyx
arquivo de origem .Aqui está uma versão resumida da
setup.py
qual espero que mostre o essencial:Também editei
MANIFEST.in
para garantir que issomycythonmodule.c
seja incluído em uma distribuição de origem (uma distribuição de origem criada compython setup.py sdist
):Não me comprometo
mycythonmodule.c
com o controle de versão 'trunk' (ou 'padrão' para o Mercurial). Ao fazer um lançamento, lembre-se de fazer opython setup.py build_ext
primeiro, para garantir quemycythonmodule.c
esteja presente e atualizado para a distribuição do código-fonte. Também faço uma ramificação de liberação e submeto o arquivo C na ramificação. Dessa forma, eu tenho um registro histórico do arquivo C que foi distribuído com essa versão.fonte
Adicionando à resposta de Craig McQueen: veja abaixo como substituir o
sdist
comando para que o Cython compile automaticamente seus arquivos de origem antes de criar uma distribuição de origem.Dessa forma, você não corre o risco de distribuir acidentalmente
C
fontes desatualizadas . Também ajuda no caso de você ter controle limitado sobre o processo de distribuição, por exemplo, ao criar automaticamente distribuições a partir de integração contínua etc.fonte
http://docs.cython.org/en/latest/src/userguide/source_files_and_compilation.html#distributing-cython-modules
fonte
O mais fácil é incluir os dois, mas basta usar o arquivo c? Incluir o arquivo .pyx é bom, mas não é necessário depois que você tiver o arquivo .c. As pessoas que desejam recompilar o .pyx podem instalar o Pyrex e fazê-lo manualmente.
Caso contrário, você precisará ter um comando build_ext personalizado para distutils que constrói o arquivo C primeiro. Cython já inclui um. http://docs.cython.org/src/userguide/source_files_and_compilation.html
O que essa documentação não faz é dizer como tornar isso condicional, mas
Deve lidar com isso.
fonte
setup.py
pode construir diretamente a partir do.pyx
arquivo quando o Cython está instalado. Minha resposta implementou isso também.Incluir arquivos .c gerados (Cython) é bem estranho. Especialmente quando incluímos isso no git. Eu preferiria usar setuptools_cython . Quando o Cython não estiver disponível, ele criará um ovo que possui o ambiente Cython interno e, em seguida, seu código usando o ovo.
Um possível exemplo: https://github.com/douban/greenify/blob/master/setup.py
Atualização (05-01-2017):
Desde
setuptools 18.0
, não há necessidade de usarsetuptools_cython
. Aqui está um exemplo para criar o projeto Cython do zero semsetuptools_cython
.fonte
'setuptools>=18.0'
setup_requires em vez de criar o métodois_installed
?setuptools>=18.0
ter sido instalado, então você só precisa colocar'Cython >= 0.18'
emsetup_requires
e Cython será instalado durante a instalação progresso. Mas se você estiver usando o setuptools <18.0, mesmo o cython específico em setup_requires, ele não será instalado; nesse caso, você deve considerar o usosetuptools_cython
.pip install wheel
. Então deve ser o motivo 1. Instale a roda primeiro e tente novamente.Este é um script de configuração que escrevi que facilita a inclusão de diretórios aninhados dentro da compilação. É necessário executá-lo da pasta dentro de um pacote.
Estrutura Givig como esta:
setup.py
Compilação feliz;)
fonte
O hack simples que eu criei:
Basta instalar o Cython se não puder ser importado. Provavelmente não se deve compartilhar esse código, mas para minhas próprias dependências é bom o suficiente.
fonte
Todas as outras respostas contam com
Cython.Build
, o que cria um problema de galinha e ovo entre exigir o cython viasetup_requires
e importá-lo.Uma solução moderna é usar o setuptools, veja esta resposta (o manuseio automático das extensões Cython requer o setuptools 18.0, ou seja, já está disponível há muitos anos). Um padrão moderno
setup.py
com manipulação de requisitos, um ponto de entrada e um módulo cython poderia ter esta aparência:fonte
Cython.Build
no momento da instalação causa ImportError para mim. Ter setuptools para compilar pyx é a melhor maneira de fazer isso.A maneira mais fácil que encontrei usando apenas as ferramentas de instalação em vez dos recursos distutils limitados é
fonte
Cython.Build
, veja minha resposta.Acho que encontrei uma maneira muito boa de fazer isso fornecendo um
build_ext
comando personalizado . A ideia é a seguinte:Eu adiciono os cabeçalhos numpy substituindo
finalize_options()
e executandoimport numpy
no corpo da função, o que evita o problema de o numpy não estar disponível antes dasetup()
instalação.Se o cython estiver disponível no sistema, ele se conecta ao
check_extensions_list()
método do comando e cythoniza todos os módulos cython desatualizados, substituindo-os por extensões C que podem ser tratadas posteriormente pelobuild_extension()
método. Também fornecemos a última parte da funcionalidade em nosso módulo: isso significa que, se o cython não estiver disponível, mas tivermos uma extensão C presente, ele ainda funcionará, o que permite fazer distribuições de código-fonte.Aqui está o código:
Isso permite que você escreva os
setup()
argumentos sem se preocupar com as importações e se existe um cython disponível:fonte