Jak znaleźć zależności pakietu Pythona

106

Jak programowo uzyskać listę zależności pakietu Pythona?

Standard setup.pyma to udokumentowane, ale nie mogę znaleźć łatwego sposobu, aby uzyskać do niego dostęp z Pythona lub wiersza poleceń.

Idealnie szukam czegoś takiego:

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

lub:

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

Uwaga, nie mówię o importowaniu pakietu i znajdowaniu wszystkich przywoływanych modułów. Chociaż może to znaleźć większość pakietów zależnych, nie byłoby w stanie znaleźć wymaganego minimalnego numeru wersji. To jest przechowywane tylko w pliku setup.py.

Cerin
źródło
Sporo odpowiedzi tutaj pokazuje, że pip jest importowany do użytku w programach. Dokumentacja pip zdecydowanie odradza korzystanie z tej pip. Coś, o czym należy pamiętać, jeśli którekolwiek z tych rozwiązań jest używane do czegoś ważnego.
Jordan Mackie,

Odpowiedzi:

97

Oprócz pip show [package name]polecenia istnieje pipdeptree.

Po prostu zrób

$ pip install pipdeptree

następnie uruchomić

$ pipdeptree

i pokaże ci twoje zależności w formie drzewa, np.

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]

Projekt znajduje się pod adresem https://github.com/naiquevin/pipdeptree , gdzie znajdziesz również informacje o użytkowaniu.

beruic
źródło
7
pipdeptreepokazuje zależności wszystkich zainstalowanych pakietów, a nie tylko tych z danego pakietu. Chociaż można filtrować jego --jsondane wyjściowe, nadal zależy to od pakietów, które są już zainstalowane.
sschuberth
To prawda, ale odpowiedź jest nadal przydatna, gdy chcesz dowiedzieć się, dlaczego zainstalowano pakiety, których nie ma w twoim requirements.txt:)
beruic
3
Ponadto możesz użyć -popcji, aby wybrać tylko kilka pakietów, których zależności chcesz zbadać.
Zaccharie Ramzi
2
pipdeptreebył bardzo pomocny podczas optymalizacji requirements.txt. $ pipdeptree | grep -P '^\w+' Wyprowadza tylko pakiety najwyższego poziomu. Więcej informacji tutaj
główny programista,
64

Spróbuj użyć showpolecenia w pip, na przykład:

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

Aktualizacja (pobieranie plików z określoną wersją):

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
źródło
1
To mówi ci o wersji pakietu , a nie o jego zależnościach ; po prostu pojawiają się na liście.
jonrsharpe
Zobacz Requiressekcję
Alex Lisovoy
3
Tak, ale nie wyświetla "minimalnego wymaganego numeru wersji" , ponieważ PO wymaga:
jonrsharpe
1
Jakoś wydaje mi się, $ pip3 show beautifulsoup4że jest pusty Requires: - czy beautifulsoup4 nie zależy od niczego?
xealits
4
@PythonJin, tak, najwyraźniej używa tylko standardowych pakietów .. Po prostu byłem tym trochę zaskoczony. Brawo beautifulsoup4.
xealits
6

Sporo odpowiedzi tutaj pokazuje, że pip jest importowany do użytku w programach. Dokumentacja pip zdecydowanie odradza korzystanie z tej pip .

Zamiast uzyskiwać dostęp pkg_resourcesza pośrednictwem importu pip, możesz po prostu zaimportować pkg_resourcesbezpośrednio i użyć tej samej logiki (co jest w rzeczywistości jednym z sugerowanych rozwiązań w dokumentach pip połączonych dla każdego, kto chce programowo zobaczyć metainformacje pakietu).

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()]

Jeśli masz problemy ze znalezieniem dokładnej nazwy pakietu, WorkingSetinstancja zwrócona przez pkg_resources.working_setnarzędzia, __iter__dzięki czemu możesz wydrukować je wszystkie i miejmy nadzieję, że znajdziesz tam swoją :)

to znaczy

import pkg_resources

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

Działa to zarówno z pythonem 2, jak i 3 (chociaż musisz dostosować instrukcje print dla python2)

Jordan Mackie
źródło
3

(TO JEST ODPOWIEDŹ NA DZIEDZICTWO I NALEŻY UNIKAĆ NOWOCZESNYCH WERSJI PIP I POZOSTAWIĆ TUTAJ W CELU ODNIESIENIA DO STARSZYCH WERSJI PIP) Odpowiedź Alexa jest dobra (+1). W Pythonie:

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

powinien zwrócić coś takiego jak

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

gdzie twisted to nazwa pakietu, którą można znaleźć w słowniku:

pip._vendor.pkg_resources.WorkingSet().entry_keys

aby je wszystkie wymienić:

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))

powinien dać ci takie listy:

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
źródło
Czy coś się zmieniło w ostatnich wersjach? _vendorAtrybut nie wydaje się istnieć w wersji pip 19.1.1(Edit: W porządku, wydaje się, że przeniósł się do pkg_resourcesspakowania w najnowszej wersji Pythona!)
Prahlada Yeri
Tak, wszystko się zmieniło i zamierzam spojrzeć na aktualizację tego lub usunięcie go na korzyść poniższej rekomendacji.
cgseller
Odpowiedź Alexa jest tylko częściowo lepsza z mojego punktu widzenia (cóż, pip showczęść jest dobra, a nie reszta). Albo użyjpip show , pipdeptree lub zobaczyć odpowiedź Jordan Mackie Korzystanie setuptools " pkg_resourcesbezpośrednio.
sinoroc
2

Użyj https://libraries.io/ . Jest to dobre miejsce do zbadania zależności przed instalacją przy użyciu pip.

Na przykład. Wpisz google-cloud-storage i wyszukaj, a następnie możesz znaleźć stronę biblioteki ( https://libraries.io/rubygems/google-cloud-storage ). Wybierz wersję, dla której chcesz zbadać zależności z „Wersji” (domyślnie jest to najnowsza). W sekcji „Zależności” możesz znaleźć listę zależności i ich obsługiwane wersje.

Praboda
źródło
1

Spróbuj tego zgodnie z tym artykułem w Pythonie:

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)

Będzie wyglądać następująco:

['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
źródło