Como encontrar as dependências de um pacote Python

103

Como você pode obter programaticamente a lista de dependências de um pacote Python?

O padrão setup.pytem isso documentado, mas não consigo encontrar uma maneira fácil de acessá-lo a partir do Python ou da linha de comando.

Idealmente, procuro algo como:

$ pip install somepackage --only-list-deps
kombu>=3.0.8
billiard>=3.3.0.13
boto>=2.26

ou:

>>> import package_deps
>>> package = package_deps.find('somepackage')
>>> print package.dependencies
['kombu>=3.0.8', 'billiard>=3.3.0.13', 'boto>=2.26']

Observe, não estou falando sobre importar um pacote e encontrar todos os módulos referenciados. Embora isso possa localizar a maioria dos pacotes dependentes, não seria capaz de encontrar o número de versão mínimo necessário. Isso é armazenado apenas no setup.py.

Cerin
fonte
Algumas respostas aqui mostram pip sendo importado para uso em programas. A documentação do pip desaconselha fortemente o uso de pip. Algo para ter em mente caso alguma dessas soluções esteja sendo usada para algo importante.
Jordan Mackie

Respostas:

97

Além do pip show [package name]comando, existe pipdeptree.

Apenas faça

$ pip install pipdeptree

então corra

$ pipdeptree

e mostrará suas dependências em forma de árvore, por exemplo,

flake8==2.5.0
  - mccabe [required: >=0.2.1,<0.4, installed: 0.3.1]
  - pep8 [required: !=1.6.0,>=1.5.7,!=1.6.1,!=1.6.2, installed: 1.5.7]
  - pyflakes [required: >=0.8.1,<1.1, installed: 1.0.0]
ipdb==0.8
  - ipython [required: >=0.10, installed: 1.1.0]

O projeto está localizado em https://github.com/naiquevin/pipdeptree , onde você também encontrará informações de uso.

beruic
fonte
7
pipdeptreemostra as dependências de todos os pacotes instalados , não apenas as de um determinado pacote. Embora você possa filtrar sua --jsonsaída, ela ainda depende dos pacotes já instalados.
sschuberth 01 de
Verdade, mas a resposta ainda é útil quando você deseja saber por que foram instalados pacotes que não estão em seu requirements.txt:)
beruic 01 de
3
Além disso, você pode usar a -popção de selecionar apenas alguns pacotes cujas dependências deseja explorar.
Zaccharie Ramzi
2
pipdeptreefoi muito útil na otimização requirements.txt. $ pipdeptree | grep -P '^\w+' Isso gera apenas pacotes de nível superior. Mais informações aqui
Desenvolvedor Líder de
63

Tente usar o showcomando pip, por exemplo:

$ pip show tornado
---
Name: tornado
Version: 4.1
Location: *****
Requires: certifi, backports.ssl-match-hostname

Atualizar (recuperar deps com a versão especificada):

from pip._vendor import pkg_resources


_package_name = 'somepackage'
_package = pkg_resources.working_set.by_key[_package_name]

print([str(r) for r in _package.requires()])  # retrieve deps from setup.py

Output: ['kombu>=3.0.8', 
         'billiard>=3.3.0.13', 
         'boto>=2.26']
Alex Lisovoy
fonte
1
Isso informa a versão do pacote , não suas dependências ; eles apenas são listados.
jonrsharpe
Consulte a Requiresseção
Alex Lisovoy
3
Sim, mas não mostra "o número de versão mínimo necessário" , pois o OP exige:
jonrsharpe
1
De alguma forma $ pip3 show beautifulsoup4, Requires: parece vazio para mim - beautifulsoup4 não depende de nada?
xealits de
4
@PythonJin, sim, aparentemente ele usa apenas pacotes padrão .. Eu só fiquei um pouco surpreso com isso. Muito bem beautifulsoup4.
xealits de
6

Algumas respostas aqui mostram pip sendo importado para uso em programas. A documentação do pip desaconselha fortemente o uso de pip .

Em vez de acessar pkg_resourcespor meio da importação do pip, você pode apenas importar pkg_resourcesdiretamente e usar a mesma lógica (que é, na verdade, uma das soluções sugeridas nos documentos do pip vinculados para qualquer pessoa que deseja ver as meta informações do pacote programaticamente).

import pkg_resources

_package_name = 'yourpackagename'

def get_dependencies_with_semver_string():
    package = pkg_resources.working_set.by_key[_package_name]
    return [str(r) for r in package.requires()]

Se você está tendo problemas para descobrir exatamente qual é o nome do seu pacote, a WorkingSetinstância retornada por pkg_resources.working_setimplementos __iter__para que você possa imprimir todos eles e, com sorte, localizar o seu lá :)

ie

import pkg_resources

def print_all_in_working_set():
    ws = pkg_resources.working_set
    for package_name in ws:
        print(ws)

Isso funciona com python 2 e 3 (embora você precise ajustar as instruções de impressão para python2)

Jordan Mackie
fonte
3

(ESTA É UMA RESPOSTA LEGADO E DEVE SER EVITADA PARA VERSÕES MODERNAS DE PIP E ESQUERDA AQUI PARA REFERÊNCIA A VERSÕES DE PIP ANTERIORES) A resposta de Alex é boa (+1). Em python:

pip._vendor.pkg_resources.working_set.by_key['twisted'].requires()

deve retornar algo como

[Requirement.parse('zope.interface>=3.6.0')]

onde twisted é o nome do pacote, que você pode encontrar no dicionário:

pip._vendor.pkg_resources.WorkingSet().entry_keys

para listar todos eles:

dict = pip._vendor.pkg_resources.WorkingSet().entry_keys
for key in dict:
    for name in dict[key]:
        req =pip._vendor.pkg_resources.working_set.by_key[name].requires()
        print('pkg {} from {} requires {}'.format(name,
                                                  key,
                                                  req))

deve lhe dar listas como esta:

pkg pyobjc-framework-syncservices from /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC requires [Requirement.parse('pyobjc-core>=2.5.1'), Requirement.parse('pyobjc-framework-Cocoa>=2.5.1'), Requirement.parse('pyobjc-framework-CoreData>=2.5.1')]
cgseller
fonte
Algo mudou nas versões recentes? O _vendoratributo não parece existir na versão pip 19.1.1(Editar: Tudo bem, parece ter mudado para o pkg_resourcespacote na última versão python!)
Prahlad Yeri
Sim, as coisas mudaram e irei atualizar ou remover em favor da recomendação abaixo.
cgseller
A resposta de Alex é apenas parcialmente melhor do meu ponto de vista (bem, a pip showparte é boa, não o resto). De qualquer uso pip show, pipdeptree ou ver a resposta de Jordan Mackie usando setuptools ' pkg_resourcesdiretamente.
sinoroc
2

Use https://libraries.io/ . É um bom lugar para explorar as dependências antes de instalar usando o pip.

Por exemplo. Digite google-cloud-storage e search, então você pode localizar a página da biblioteca ( https://libraries.io/rubygems/google-cloud-storage ). Selecione a versão para a qual deseja explorar as dependências em 'Releases' (o padrão é o mais recente). Em 'Dependências', você pode encontrar a lista de dependências e suas versões com suporte.

Praboda
fonte
1

Tente isso de acordo com este artigo em python:

import pip 
installed_packages = pip.get_installed_distributions()
installed_packages_list = sorted(["%s==%s" % (i.key, i.version)
     for i in installed_packages]) 
print(installed_packages_list)

Será mostrado como:

['behave==1.2.4', 'enum34==1.0', 'flask==0.10.1', 'itsdangerous==0.24', 
 'jinja2==2.7.2', 'jsonschema==2.3.0', 'markupsafe==0.23', 'nose==1.3.3', 
 'parse-type==0.3.4', 'parse==1.6.4', 'prettytable==0.7.2', 'requests==2.3.0',
 'six==1.6.1', 'vioozer-metadata==0.1', 'vioozer-users-server==0.1', 
 'werkzeug==0.9.4']
Enigma
fonte