Eu tenho um requirements.txt
arquivo que estou usando com o Travis-CI. Parece bobagem duplicar os requisitos em ambos requirements.txt
e setup.py
, portanto, eu esperava passar um identificador de arquivo para o install_requires
kwarg setuptools.setup
.
Isso é possível? Se sim, como devo proceder?
Aqui está o meu requirements.txt
arquivo:
guessit>=0.5.2
tvdb_api>=1.8.2
hachoir-metadata>=1.3.3
hachoir-core>=1.3.3
hachoir-parser>=1.3.4
install_requires
é usado para declarar dependências nos pacotes que são necessários para o pacote funcionar e são usados pelo desenvolvedor do pacote, enquantorequirements.txt
é usado para automatizar a instalação de ambientes, o que permite a instalação de software extra e a fixação da versão e são usados pelos administradores de sistemas que implementam o pacote. pacote. Seu papel e público-alvo diferem significativamente; portanto, tentar combiná-los como os desejos do OP é um verdadeiro erro de design.[line.strip() for line in open("requirements.txt").readlines()]
?pkg_resources.parse_requirements()
Respostas:
Você pode inverter e listar as dependências
setup.py
e ter um único caractere - um ponto.
- em seurequirements.txt
lugar.Como alternativa, mesmo que não seja recomendado, ainda é possível analisar o
requirements.txt
arquivo (se não referir nenhum requisito externo pela URL) com o seguinte hack (testado compip 9.0.1
):Isso não filtra os marcadores de ambiente .
Nas versões antigas do pip, mais especificamente anteriores à 6.0 , há uma API pública que pode ser usada para isso. Um arquivo de requisitos pode conter comments (
#
) e pode incluir alguns outros arquivos (--requirement
ou-r
). Portanto, se você realmente deseja analisar um,requirements.txt
pode usar o analisador de pip:fonte
setup(..., dependency_links=[str(req_line.url) for req_line in parse_requirements(<requirements_path>)], ...)
pip
padrão é analisar as dependênciassetup.py
na ausência derequirements.txt
, a resposta simples observada astutamente por Tobu abaixo é listar todas as dependênciassetup.py
e removerrequirements.txt
. Para aplicativos que exigem os dois, basta reduzir a lista de dependênciasrequirements.txt
apenas para o.
caractere. Feito.Em face disso, parece que
requirements.txt
esetup.py
são duplicatas tolas, mas é importante entender que enquanto a forma é semelhante, a função pretendida é muito diferente.O objetivo de um autor de pacote, ao especificar dependências, é dizer "onde quer que você instale este pacote, esses são os outros pacotes necessários para que este pacote funcione".
Por outro lado, o autor da implantação (que pode ser a mesma pessoa em um momento diferente) tem um trabalho diferente, pois diz "aqui está a lista de pacotes que reunimos e testamos e que agora preciso instalar".
O autor do pacote escreve para uma ampla variedade de cenários, porque eles estão enviando seu trabalho para serem usados de maneiras que talvez não conheçam e não têm como saber quais pacotes serão instalados junto com o pacote. Para ser um bom vizinho e evitar conflitos de versão de dependência com outros pacotes, eles precisam especificar o maior número de versões de dependência possível. Isto é o que
install_requires
nossetup.py
faz.O autor da implantação grava para um objetivo muito diferente e muito específico: uma única instância de um aplicativo ou serviço instalado, instalado em um computador específico. Para controlar com precisão uma implantação e garantir que os pacotes corretos sejam testados e implantados, o autor da implantação deve especificar a versão exata e o local de origem de cada pacote a ser instalado, incluindo dependências e dependências. Com essa especificação, uma implantação pode ser aplicada repetidamente em várias máquinas ou testada em uma máquina de teste, e o autor da implantação pode ter certeza de que os mesmos pacotes são implantados sempre. Isto é o que a
requirements.txt
faz.Então você pode ver que, embora ambos pareçam uma grande lista de pacotes e versões, essas duas coisas têm tarefas muito diferentes. E é definitivamente fácil misturar tudo e errar! Mas a maneira correta de pensar sobre isso é que
requirements.txt
é uma "resposta" à "pergunta" feita pelos requisitos em todos os váriossetup.py
arquivos de pacotes. Em vez de escrevê-lo manualmente, geralmente é gerado dizendo ao pip para olhar para todos ossetup.py
arquivos em um conjunto de pacotes desejados, encontrar um conjunto de pacotes que julgue adequado a todos os requisitos e, depois de instalados, "congelar" "essa lista de pacotes em um arquivo de texto (é daí que opip freeze
nome vem).Então, a dica:
setup.py
deve declarar as versões de dependência mais baixas possíveis que ainda sejam viáveis. Seu trabalho é dizer com o que um pacote específico pode funcionar.requirements.txt
é um manifesto de implantação que define todo um trabalho de instalação e não deve ser considerado vinculado a nenhum pacote. Seu trabalho é declarar uma lista exaustiva de todos os pacotes necessários para fazer uma implantação funcionar.Referências:
fonte
requirements.txt
juntamente com a fonte do pacote que contém os requisitos concretos / congelados para instalação ou teste. Certamentesetup.py
pode ser usado para esse fim dentro do próprio projeto? Só posso imaginar usar esse arquivo para ferramentas usadas para dar suporte ao gerenciamento do projeto (por exemplo, refatoração, lançamento de lançamentos etc.).requirements.txt
há mais documentação para o estado do mundo que produziu uma determinada compilação, mesmo que ela não seja normalmente usada no próprio processo de compilação? Isso faz sentido. No entanto, parece que vários sistemas dependem de duplicação: O Travis instala alguns pacotes (antigos) padrão no seu virtualenv e diz para usá-lorequirements.txt
. Se eu perguntar como garantir que as dependências sejamsetup.py
usadas o mais tardar , as pessoas insistem que eu deveria usarrequirements.txt
.Não é possível lidar com um arquivo. O
install_requires
argumento pode ser apenas uma string ou uma lista de strings .Obviamente, você pode ler seu arquivo no script de instalação e passá-lo como uma lista de strings para
install_requires
.fonte
install_requires
. No entanto, não funcionará se você não usar sintaxe declarativa.setup.py
é um programa que deve ser executado, não um arquivo de dados que deve ser analisado. Isso não piora a resposta.include requirements.txt
no seuMANIFEST.in
ou você não poderá instalar sua biblioteca a partir de uma distribuição de origem.Os arquivos de requisitos usam um formato de pip expandido, que só é útil se você precisar complementá-lo
setup.py
com restrições mais fortes, por exemplo, especificando os URLs exatos dos quais algumas dependências devem provir ou a saída depip freeze
para congelar todo o pacote definido como conhecido. versões. Se você não precisar de restrições extras, use apenas asetup.py
. Se você sentir que realmente precisa enviar um derequirements.txt
qualquer maneira, crie uma única linha:Será válido e se referirá exatamente ao conteúdo do
setup.py
que está no mesmo diretório.fonte
pip install -r requirements.txt
) sem instalar o próprio pacote?-e .
deve ser suficiente. Verifique esta página: caremad.io/posts/2013/07/setup-vs-requirementEmbora não seja uma resposta exata para a pergunta, recomendo a publicação no blog de Donald Stufft em https://caremad.io/2013/07/setup-vs-requirement/ para uma boa compreensão desse problema. Eu tenho usado com muito sucesso.
Em suma,
requirements.txt
não é umasetup.py
alternativa, mas um complemento de implantação. Mantenha uma abstração apropriada das dependências do pacote emsetup.py
. Defina umrequirements.txt
ou mais deles para buscar versões específicas de dependências de pacotes para desenvolvimento, teste ou produção.Por exemplo, com pacotes incluídos no repositório em
deps/
:O pip executa os pacotes
setup.py
e instala as versões específicas das dependências declaradas eminstall_requires
. Não há duplicidade e o objetivo de ambos os artefatos é preservado.fonte
pip install my-package
. Se as dependências do my-package não estiverem listadas em my-package / setup.py, elas não serão instaladas porpip install my-package
. Não consegui determinar como fornecer um pacote para outras pessoas que inclua dependências sem explicitamente explicá-las em setup.py. Gostaria de saber se alguém descobriu como mantê-lo seco enquanto permite que outros instalem dependências my-package + sem baixar o arquivo de requisitos e chamar manualmentepip install -r my-package/requirements.txt
.requirements.txt
. Esse é o ponto. Atualizada a pergunta para tornar as coisas mais claras. Também foi atualizado o link obsoleto da postagem do blog.O uso
parse_requirements
é problemático porque a API do pip não é documentada e suportada publicamente. No pip 1.6, essa função está realmente em movimento, portanto, os usos existentes dela provavelmente serão interrompidos.Uma maneira mais confiável de eliminar a duplicação entre
setup.py
erequirements.txt
é especificar suas dependênciassetup.py
e colocá-e .
- las norequirements.txt
arquivo. Algumas informações de um dospip
desenvolvedores sobre por que esse é o melhor caminho estão disponíveis aqui: https://caremad.io/blog/setup-vs-requirement/fonte
A maioria das outras respostas acima não funciona com a versão atual da API do pip. Aqui está a maneira correta * de fazer isso com a versão atual do pip (6.0.8 no momento da redação, também trabalhada no 7.1.2. Você pode verificar sua versão com o pip -V).
* Correto, pois é a maneira de usar parse_requirements com o pip atual. Provavelmente ainda não é a melhor maneira de fazê-lo, pois, como os pôsteres acima disseram, o pip realmente não mantém uma API.
fonte
Instale o pacote atual no Travis. Isso evita o uso de um
requirements.txt
arquivo. Por exemplo:fonte
pip freeze
e exporte esse arquivo para algum lugar como um artefato (como S3 ou algo assim), você terá uma ótima maneira de instalar repetidamente exatamente o que você testado.from pip.req import parse_requirements
não funcionou para mim e acho que é para as linhas em branco nos meus requisitos.txt, mas essa função funcionafonte
Se você não deseja forçar seus usuários a instalar o pip, você pode emular seu comportamento com isso:
fonte
A seguinte interface ficou obsoleta no pip 10:
Então, eu mudei apenas para a análise de texto simples:
fonte
pathlib
variação dela.Essa abordagem simples lê o arquivo de requisitos em
setup.py
. É uma variação da resposta de Dmitiry S .. Esta resposta é compatível apenas com Python 3.6+.Por DS ,
requirements.txt
pode documentar requisitos concretos com números de versão específicos, enquantosetup.py
pode documentar requisitos abstratos com intervalos de versões soltas.Abaixo está um trecho do meu
setup.py
.Observe que
distutils.text_file.TextFile
isso removerá os comentários. Além disso, pela minha experiência, você aparentemente não precisa executar nenhuma etapa especial para agrupar o arquivo de requisitos.fonte
Cuidado com o
parse_requirements
comportamento!Observe que
pip.req.parse_requirements
os sublinhados serão alterados para traços. Isso me enfureceu por alguns dias antes que eu o descobrisse. Exemplo demonstrando:produz
fonte
[ir.req.unsafe_name for ir in req_deps if ir.req is not None]
Eu criei uma função reutilizável para isso. Na verdade, ele analisa um diretório inteiro de arquivos de requisitos e os define como extras_require.
Últimas sempre disponíveis aqui: https://gist.github.com/akatrevorjay/293c26fefa24a7b812f5
fonte
pip._internal
.. Se você não fornece uma API externa utilizável, não deve quebrar tudo isso que estão usando tudo o que você fornece.Outra solução possível ...
e depois usar ...
fonte
tree
vem?Eu não recomendaria fazer isso. Como mencionado várias vezes
install_requires
erequirements.txt
definitivamente não deveria ser a mesma lista. Mas como existem muitas respostas enganosas envolvendo APIs internas privadas de pip , pode valer a pena procurar alternativas mais saudáveis ...Não há necessidade de o pip analisar um
requirements.txt
arquivo a partir de um script setuptoolssetup.py
. O projeto setuptools já contém todas as ferramentas necessárias em seu pacote de nível superiorpkg_resources
.Poderia ser mais ou menos assim:
fonte
pip
a análise de e nãopkg_resources
desde antes de 2015 são bugs, como github.com/pypa/setuptools/issues/470 . Esse exato é corrigido hoje em dia, mas ainda tenho um pouco de medo de usá-lo, pois as duas implementações parecem ser desenvolvidas separadamente.Postando minha resposta dessa pergunta SO para outra solução simples e à prova de versão de pip.
Em seguida, basta inserir todos os seus requisitos no
requirements.txt
diretório raiz do projeto.fonte
Eu fiz isso:
fonte
Outro
parse_requirements
truque que também analisa marcadores de ambiente emextras_require
:Ele deve suportar discos sdist e binários.
Conforme declarado por outros,
parse_requirements
possui várias deficiências, portanto, não é isso que você deve fazer em projetos públicos, mas pode ser suficiente para projetos internos / pessoais.fonte
parse_requirements()
, então isso agora falha.Aqui está um hack completo (testado com
pip 9.0.1
) baseado na resposta de Romain que o analisarequirements.txt
e filtra de acordo com os marcadores de ambiente atuais :fonte
r.match_markers()
está realmente avaliando os marcadores, o que é a coisa certa a fazer para um sdist. No entanto, se você estiver construindo um dist binário (por exemplo, wheel), o pacote listará apenas as bibliotecas que correspondem ao seu ambiente de tempo de construção.wheel environment
(se é o que a pessoa tenta fazer) para avaliar marcadores?bdist_wheel
. Não avalia marcadores, apenas os adicionaextras_require
.