Como eu consegui definir a versão setup.py
do meu pacote (para --version
ou para outros fins)?
python
setuptools
elmarco
fonte
fonte
Respostas:
Interrogar a sequência de versões da distribuição já instalada
Para recuperar a versão de dentro do seu pacote em tempo de execução (o que sua pergunta parece realmente estar perguntando), você pode usar:
Armazene a sequência de versões para uso durante a instalação
Se você quiser seguir o caminho inverso (que parece ser o que outros autores de respostas aqui parecem ter pensado que você estava perguntando), coloque a string da versão em um arquivo separado e leia o conteúdo desse arquivo
setup.py
.Você pode criar um version.py no seu pacote com uma
__version__
linha e, em seguida, lê-lo em setup.py usandoexecfile('mypackage/version.py')
, para que seja definido__version__
no namespace setup.py.Se você deseja uma maneira muito mais simples que funcione com todas as versões do Python e até mesmo com as linguagens que não sejam do Python, que podem precisar de acesso à string da versão:
Armazene a string da versão como o único conteúdo de um arquivo de texto sem formatação, nomeado por exemplo
VERSION
, e leia esse arquivo durantesetup.py
.O mesmo
VERSION
arquivo funcionará exatamente como em qualquer outro programa, mesmo que não seja em Python, e você só precisará alterar a string da versão em um local para todos os programas.Aviso sobre a condição de corrida durante a instalação
A propósito, NÃO importe seu pacote do setup.py, como sugerido em outra resposta aqui: ele parecerá funcionar para você (porque você já possui as dependências do pacote instaladas), mas causará estragos nos novos usuários do seu pacote. , pois eles não poderão instalar seu pacote sem instalar manualmente as dependências primeiro.
fonte
execfile
funciona muito bem ... mas (infelizmente) não funciona com o Python 3.with open('mypackage/version.py') as f: exec(f.read())
no lugar deexecfile('mypackage/version.py')
. (From stackoverflow.com/a/437857/647002 )exemplo de estudo:
mymodule
Imagine esta configuração:
Imagine um cenário comum em que você tenha dependências e se
setup.py
pareça com:E um exemplo
__init__.py
:E por exemplo
myclasses.py
:problema 1: importar
mymodule
durante a instalaçãoSe suas
setup.py
importaçõesmymodule
, durante a instalação, você provavelmente obterá umImportError
. Este é um erro muito comum quando o seu pacote tem dependências. Se o seu pacote não tiver outras dependências além das internas, você pode estar seguro; no entanto, isso não é uma boa prática. A razão para isso é que não é à prova de futuro; digamos amanhã que seu código precisa consumir alguma outra dependência.problema 2: onde está o meu
__version__
?Se você codificar
__version__
emsetup.py
seguida, ele pode não coincidir com a versão que seria lançado em seu módulo. Para ser consistente, você o colocaria em um só lugar e o leria do mesmo lugar quando necessário. Usandoimport
você pode obter o problema nº 1.solução: à la
setuptools
Você usaria uma combinação de
open
,exec
e fornecer um dicionário paraexec
as variáveis add:E em
mymodule/version.py
expor a versão:Dessa forma, a versão é fornecida com o módulo e você não apresenta problemas durante a instalação ao tentar importar um módulo que possui dependências ausentes (ainda a ser instalado).
fonte
A melhor técnica é definir
__version__
no código do produto e importá-lo para o setup.py a partir daí. Isso fornece um valor que você pode ler no seu módulo em execução e tem apenas um lugar para defini-lo.Os valores em setup.py não estão instalados e o setup.py não permanece após a instalação.
O que eu fiz (por exemplo) em composition.py:
UPDATE (2017): o cover.py não se importa mais para obter a versão. A importação do seu próprio código pode torná-lo desinstalável, porque o código do produto tentará importar dependências, que ainda não estão instaladas, porque o setup.py é o que as instala.
fonte
__version__
nele estiver quebrado de alguma forma, sua importação também será interrompida. Python não sabe como interpretar apenas as declarações que você deseja. @pjeby está certo: se o seu módulo precisar importar outros módulos, eles ainda não podem estar instalados e serão caóticos. Essa técnica funciona se você for cuidadoso para que a importação não cause uma longa cadeia de outras importações.pip install <packagename>
, eu recebo o seguinte erro:ImportError: No module named <packagename>
. AVISO aos seus leitores que você não pode executar arquivos setup.py como este em ambientes onde o pacote ainda não está instalado!Sua pergunta é um pouco vaga, mas acho que o que você está perguntando é como especificá-la.
Você precisa definir
__version__
assim:E então você pode confirmar que o setup.py conhece a versão que você acabou de especificar:
fonte
Eu não estava feliz com essas respostas ... não queria exigir ferramentas de configuração, nem criar um módulo inteiro para uma única variável, então eu vim com elas.
Para quando você tiver certeza de que o módulo principal está no estilo pep8 e permanecerá assim:
Se você deseja ser mais cuidadoso e usar um analisador real:
O setup.py é um módulo descartável, portanto não é um problema se for um pouco feio.
Atualização: engraçado o bastante, eu me afastei disso nos últimos anos e comecei a usar um arquivo separado no pacote chamado
meta.py
. Coloquei muitos metadados lá que talvez eu queira mudar com frequência. Portanto, não apenas por um valor.fonte
ast.get_docstring()
alguns.split('\n')[0].strip()
etc para preencher automaticamente adescription
partir da fonte. Menos uma coisa para manter em sincroniaCrie um arquivo na sua árvore de fontes, por exemplo, em yourbasedir / yourpackage / _version.py. Deixe esse arquivo conter apenas uma única linha de código, como esta:
__version__ = "1.1.0-r4704"
Em seguida, em seu setup.py, abra esse arquivo e analise o número da versão assim:
Finalmente, na
yourbasedir/yourpackage/__init__.py
importação _version assim:Um exemplo de código que faz isso é o pacote "pyutil" que eu mantenho. (Consulte PyPI ou pesquisa no google - o stackoverflow está me impedindo de incluir um hiperlink para ele nesta resposta.)
@pjeby está certo em não importar seu pacote de seu próprio setup.py. Isso funcionará quando você testá-lo, criando um novo interpretador Python e executando o setup.py nele: primeiro
python setup.py
, mas há casos em que ele não funciona. Isso porqueimport youpackage
não significa ler o diretório de trabalho atual para um diretório chamado "yourpackage", significa procurar no atualsys.modules
por uma chave "yourpackage" e, em seguida, fazer várias coisas se não estiver lá. Por isso, sempre funciona quando você faz,python setup.py
porque você tem um novo, vaziosys.modules
, mas isso não funciona em geral.Por exemplo, e se o py2exe estiver executando o setup.py como parte do processo de empacotamento de um aplicativo? Eu já vi um caso como este em que py2exe colocaria o número da versão incorreta em um pacote porque o pacote estava obtendo o número da versão em
import myownthing
em seu setup.py, mas uma versão diferente desse pacote havia sido importada anteriormente durante a execução do py2exe. Da mesma forma, e se setuptools, easy_install, distribuir ou distutils2 estiver tentando criar seu pacote como parte de um processo de instalação de um pacote diferente que depende do seu? Então, se o seu pacote é importável no momento em que seu setup.py está sendo avaliado, ou se já existe uma versão do seu pacote que foi importada durante a vida deste intérprete Python, ou se a importação do seu pacote exige que outros pacotes sejam instalados primeiro , ou tem efeitos colaterais, pode alterar os resultados. Eu tive várias dificuldades ao tentar reutilizar pacotes Python, o que causou problemas para ferramentas como py2exe e setuptools, porque o setup.py importa o próprio pacote para encontrar o número da versão.A propósito, essa técnica funciona bem com ferramentas para criar automaticamente o
yourpackage/_version.py
arquivo para você, por exemplo, lendo seu histórico de controle de revisões e escrevendo um número de versão com base na tag mais recente do histórico de controle de revisões. Aqui está uma ferramenta que faz isso para darcs: http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.rst e aqui está um trecho de código que faz a mesma coisa para o git: http: // github .com / warner / python-ecdsa / blob / 0ed702a9d4057ecf33eea969b8cf280eaccd89a1 / setup.py # L34fonte
Isso também deve funcionar, usando expressões regulares e dependendo dos campos de metadados para ter um formato como este:
Use o seguinte no início de seu setup.py:
Depois disso, você pode usar os metadados no seu script assim:
fonte
Com uma estrutura como esta:
onde version.py contém:
Você pode fazer isso em setup.py :
Isso não causará nenhum problema com quaisquer dependências que você tenha no seu mymodule / __ init__.py
fonte
Para evitar importar um arquivo (e, portanto, executar seu código), é possível analisá-lo e recuperar o
version
atributo da árvore de sintaxe:Este código tenta encontrar a
__version__
ou aVERSION
atribuição no nível superior do retorno do módulo é o valor da string. O lado direito pode ser uma string ou uma tupla.fonte
Existem mil maneiras de esfolar um gato - eis as minhas:
fonte
Limpando https://stackoverflow.com/a/12413800 do @ gringo-suave:
fonte
Agora, isso é grosseiro e precisa ser aprimorado (pode até haver uma chamada de membro descoberta em pkg_resources que eu perdi), mas eu simplesmente não vejo por que isso não funciona, nem por que ninguém sugeriu isso até agora (pesquisar no Google não aumentou isso) ... observe que este é o Python 2.xe requereria o pkg_resources (sigh):
fonte
Queríamos colocar as informações meta sobre o nosso pacote
pypackagery
no__init__.py
, mas não podia, uma vez que tem dependências de terceiros como PJ Eby já apontado (ver sua resposta e a advertência sobre a condição de corrida).Resolvemos isso criando um módulo separado
pypackagery_meta.py
que contém apenas as meta informações:depois importou as meta informações em
packagery/__init__.py
:e finalmente o usou em
setup.py
:Você deve incluir
pypackagery_meta
no seu pacote opy_modules
argumento de instalação. Caso contrário, você não poderá importá-lo na instalação, pois a distribuição empacotada não possui.fonte
Simples e direto, crie um arquivo chamado
source/package_name/version.py
com o seguinte conteúdo:Em seguida, no seu arquivo
source/package_name/__init__.py
, você importa a versão para outras pessoas usarem:Agora, você pode colocar isso
setup.py
Testado isso com Python
2.7
,3.3
,3.4
,3.5
,3.6
e3.7
no Linux, Windows e Mac OS. Eu usei no meu pacote que possui testes de integração e unidade para todas as plataformas de teses. Você pode ver os resultados de.travis.yml
eappveyor.yml
aqui:Uma versão alternativa está usando o gerenciador de contexto:
Você também pode usar o
codecs
módulo para lidar com erros unicode no Python2.7
e no3.6
Se você estiver escrevendo um módulo Python 100% em C / C ++ usando extensões Python C, poderá fazer a mesma coisa, mas usando C / C ++ em vez de Python.
Nesse caso, crie o seguinte
setup.py
:Que lê a versão do arquivo
version.h
:Mas, não esqueça de criar
MANIFEST.in
oversion.h
arquivo para incluir :E é integrado ao aplicativo principal com:
Referências:
fonte
implante pacote no servidor e convenção de nomenclatura de arquivos para pacotes de índices:
exemplo para conversão de versão dinâmica pip:
ganhar:
Mac:
Encontre o exemplo setup.py chama a versão do pip dinâmico correspondente ao git commit
fonte
Eu estou usando uma variável de ambiente como abaixo
VERSION = 0.0.0 python setup.py sdist bdist_wheel
Em setup.py
Para verificação de consistência com a versão do empacotador, estou usando o script abaixo.
fonte