Árbol de dependencias de un módulo de Python

En general, muchos paquetes de Python dependen de otros paquetes, pero ¿cómo sabemos de qué paquetes depende un módulo?

congelación de pepitas:

Este es un módulo incorporado de Python que puede ayudarnos a conocer los paquetes dependientes, pero muestra todas las dependencias como una lista plana, averiguar cuáles son los paquetes de nivel superior y de qué paquetes dependen requiere un poco de esfuerzo. Veamos un ejemplo de cómo funciona:

Escriba el siguiente comando en su símbolo del sistema:

$pip freeze

Producción:

altair==4.1.0
attrs==19.3.0
docutils==0.15.2
entrypoints==0.3
Jinja2==2.11.2
jmespath==0.10.0
jsonschema==3.2.0
MarkupSafe==1.1.1
numpy==1.18.4
opencv-python==4.2.0.34
pandas==1.0.4
pyrsistent==0.16.0
python-dateutil==2.8.1
pytz==2020.1
six==1.15.0
toolz==0.10.0
urllib3==1.25.9

utilidad pipdeptree:

Una forma fácil de hacerlo es usar la utilidad pipdeptree. El pipdeptree funciona en la línea de comandos y muestra los paquetes de python instalados en forma de árbol de dependencia.

Este módulo no viene integrado con Python. Para instalarlo, escriba el siguiente comando en la terminal.

$pip install pipdeptree

Esto instalará la última versión de pipdeptree que requiere al menos Python 2.7.

Ahora ejecute este comando en el símbolo del sistema para obtener un árbol de dependencia de todos sus módulos de Python.

Dominio:

$pipdeptree

Producción:

$pipdeptree
altair==4.1.0
 - entrypoints [required: Any, installed: 0.3]
 - jinja2 [required: Any, installed: 2.11.2]
   - MarkupSafe [required: >=0.23, installed: 1.1.1]
 - jsonschema [required: Any, installed: 3.2.0]
   - attrs [required: >=17.4.0, installed: 19.3.0]
   - pyrsistent [required: >=0.14.0, installed: 0.16.0]
     - six [required: Any, installed: 1.15.0]
   - setuptools [required: Any, installed: 41.2.0]
   - six [required: >=1.11.0, installed: 1.15.0]
 - numpy [required: Any, installed: 1.18.4]
 - pandas [required: >=0.18, installed: 1.0.4]
   - numpy [required: >=1.13.3, installed: 1.18.4]
   - python-dateutil [required: >=2.6.1, installed: 2.8.1]
     - six [required: >=1.5, installed: 1.15.0]
   - pytz [required: >=2017.2, installed: 2020.1]
 - toolz [required: Any, installed: 0.10.0]
docutils==0.15.2
jmespath==0.10.0
opencv-python==4.2.0.34
 - numpy [required: >=1.17.3, installed: 1.18.4]
pipdeptree==1.0.0
 - pip [required: >=6.0.0, installed: 20.2.1]
urllib3==1.25.9

Combinando pipdeptree y congelar:

Veamos qué sucede cuando usamos pipdeptree y congelamos por completo,

Dominio:

$pipdeptree --freeze

Producción:

altair==4.1.0
  entrypoints==0.3
  Jinja2==2.11.2
    MarkupSafe==1.1.1
  jsonschema==3.2.0
    attrs==19.3.0
    pyrsistent==0.16.0
      six==1.15.0
    setuptools==41.2.0
    six==1.15.0
  numpy==1.18.4
  pandas==1.0.4
    numpy==1.18.4
    python-dateutil==2.8.1
      six==1.15.0
    pytz==2020.1
  toolz==0.10.0
docutils==0.15.2
jmespath==0.10.0
Mako==1.1.3
  MarkupSafe==1.1.1
opencv-python==4.2.0.34
  numpy==1.18.4
pipdeptree==1.0.0
  pip==20.2.1
scipy==1.5.2
  numpy==1.18.4
urllib3==1.25.9

Entonces, aquí vemos que usar pipdeptree junto con congelar muestra el resultado al combinar las propiedades de ambos comandos. Entonces, parece que la salida de pip freeze indica qué paquete instaló qué otro paquete, similar a pipdeptree pero aquí se usa sangría en lugar de un guión (-) para indicar el árbol.

Advertencias en pipdeptree:

Comúnmente ocurren dos tipos de advertencias al ejecutar el comando pipdeptree , veámoslas una por una.

1. Dependencias en conflicto: como el nombre sugiere «dependencia en conflicto», también lo es su relevancia. A veces hay paquetes que se especifican como una dependencia de varios paquetes con una versión diferente, en esta situación surge una posible advertencia de dependencia en conflicto. Por lo tanto, cualquier paquete que se especifique como una dependencia de varios paquetes con una versión diferente se considera una posible dependencia en conflicto.

pipdeptree por defecto advierte sobre posibles dependencias conflictivas.

Veamos un ejemplo más de pipdeptree:

Dominio:

$pipdeptree

Producción:

Warning!!! Possibly conflicting dependencies found:
* impacket==0.9.20
 - ldap3 [required: ==2.5.1, installed: ?]
 - ldapdomaindump [required: >=0.9.0, installed: ?]
------------------------------------------------------------------------
alembic==1.0.11.dev0
attrs==18.2.0
dulwich==0.20.2
  - certifi [required: Any, installed: 2018.11.29]
  - urllib3 [required: >=1.24.1, installed: 1.24.1]
EditorConfig==0.12.1
Flask-Cors==3.0.8
  - Flask [required: >=0.9, installed: 1.1.1]
  - Six [required: Any, installed: 1.13.0]
Flask-Session==0.3.1
Flask-SocketIO==4.2.1
  - Flask [required: >=0.9, installed: 1.1.1]
  - python-socketio [required: >=4.3.0, installed: 4.5.1]
    - python-engineio [required: >=3.9.0, installed: 3.12.1]
      - six [required: >=1.9.0, installed: 1.13.0]
    - six [required: >=1.9.0, installed: 1.13.0]
google==2.0.1
  - beautifulsoup4 [required: Any, installed: 4.8.0]
html2text==2019.8.11
impacket==0.9.20
  - ldap3 [required: ==2.5.1, installed: ?]
  - ldapdomaindump [required: >=0.9.0, installed: ?]
ipython==5.8.0
  - backports.shutil-get-terminal-size [required: Any, installed: 1.0.0]
  - pathlib2 [required: Any, installed: 2.3.5]
    - scandir [required: Any, installed: 1.10.0]
  - pexpect [required: Any, installed: 4.6.0]

 pip aún no tiene una verdadera resolución de dependencia. La advertencia se imprime en stderr (error estándar) en lugar de stdout (salida estándar). Para silenciar completamente esta advertencia, use el indicador -w silent o –warn silent . También se puede hacer que el modo sea estricto con –warn fail , en cuyo caso el comando no solo imprimirá las advertencias en stderr, sino que también saldrá con un código de estado distinto de cero. Esto podría ser útil si desea incluir esta herramienta en su canalización de CI.

Nota: El indicador –warn se agregó en la versión 0.6.0. Para una versión anterior, use el indicador –nowarn.

2. Dependencias circulares: esta dependencia ocurre cuando dos paquetes dependen el uno del otro. Supongamos que el paquete A depende del paquete B y el paquete B depende del paquete A.

Para ello veamos un ejemplo más:

Dominio:

$pipdeptree

Producción:

Warning!!! Cyclic dependencies found:
- CircularDependencyA => CircularDependencyB => CircularDependencyA
- CircularDependencyB => CircularDependencyA => CircularDependencyB
------------------------------------------------------------------------
wsgiref==0.1.2
argparse==1.2.1

Nota: También se imprimen en stderr y se pueden controlar mediante el indicador –warn.

Para saber por qué está instalado un paquete en particular:

Ahora, a veces podemos querer saber por qué se instala un paquete en particular. Entonces podemos usar el indicador –reverse (o simplemente -r) para esto. Para averiguar qué paquetes requieren un paquete en particular, se puede combinar con –packages

marca como se muestra en el siguiente ejemplo:

Comando :

$pipdeptree --reverse --packages MarkupSafe,numpy

Producción:

MarkupSafe==1.1.1
  - Jinja2==2.11.2 [requires: MarkupSafe>=0.23]
    - altair==4.1.0 [requires: jinja2]
  - Mako==1.1.3 [requires: MarkupSafe>=0.9.2]
numpy==1.18.4
  - altair==4.1.0 [requires: numpy]
  - opencv-python==4.2.0.34 [requires: numpy>=1.17.3]
  - pandas==1.0.4 [requires: numpy>=1.13.3]
    - altair==4.1.0 [requires: pandas>=0.18]
  - scipy==1.5.2 [requires: numpy>=1.14.5]

Usando pipdeptree para escribir el archivo requirements.txt:

Si desea rastrear solo los paquetes de nivel superior en su archivo requirements.txt , es posible hacerlo usando pipdeptree haciendo grep-ing solo en las líneas de nivel superior de la salida,

Dominio:

$pipdeptree | grep -P '^\w+'

Producción:

Lookupy==0.1
wsgiref==0.1.2
argparse==1.2.1
psycopg2==2.5.2
Flask-Script==0.6.6
alembic==0.6.2
ipython==2.0.0
slugify==0.0.1
redis==2.9.1

Sin embargo, aquí hay un problema. El resultado no menciona nada sobre la instalación de Lookupy como un paquete editable (consulte el resultado de pip freeze anterior) y se pierde información sobre su origen. Para solucionar esto, pipdeptree debe ejecutarse con un indicador -f o –freeze

Dominio:

$pipdeptree -f --warn silence | grep -P '^[\w0-9\-=.]+'

Producción:

-e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy-master
wsgiref==0.1.2
argparse==1.2.1
psycopg2==2.5.2
Flask-Script==0.6.6
alembic==0.6.2
ipython==2.0.0
slugify==0.0.1
redis==2.9.1

Dominio:

$ pipdeptree -f --warn silence | grep -P '^[\w0-9\-=.]+' > requirements.txt

El indicador de congelación tampoco generará los guiones para las dependencias secundarias, por lo que puede volcar la salida completa de pipdeptree -f en el archivo requirements.txt , lo que hace que el archivo sea amigable para los humanos (debido a las sangrías) y pip. (Sin embargo, tenga cuidado con las dependencias duplicadas)

Usando pipdeptree con herramientas externas:

pipdeptree usa flag –json para mostrar la salida en representación JSON, como se muestra a continuación:

Dominio:

$pipdeptree --json

Producción:

[
    {
        "package": {
            "key": "werkzeug",
            "package_name": "Werkzeug",
            "installed_version": "1.0.1"
        },
        "dependencies": []
    },
    {
        "package": {
            "key": "urllib3",
            "package_name": "urllib3",
            "installed_version": "1.25.9"
        },
        "dependencies": []
    },
    
    {
        "package": {
            "key": "pytz",
            "package_name": "pytz",
            "installed_version": "2020.1"
        },
        "dependencies": []
    },
    {
        "package": {
            "key": "python-dateutil",
            "package_name": "python-dateutil",
            "installed_version": "2.8.1"
        },
        "dependencies": [
            {
                "key": "six",
                "package_name": "six",
                "installed_version": "1.15.0",
                "required_version": ">=1.5"
            }
        ]
    },
    {
        "package": {
            "key": "pyrsistent",
            "package_name": "pyrsistent",
            "installed_version": "0.16.0"
        },
        "dependencies": [
            {
                "key": "six",
                "package_name": "six",
                "installed_version": "1.15.0",
                "required_version": null
            }
        ]
    },
    {
        "package": {
            "key": "pipdeptree",
            "package_name": "pipdeptree",
            "installed_version": "1.0.0"
        },
        "dependencies": [
            {
                "key": "pip",
                "package_name": "pip",
                "installed_version": "20.2.1",
                "required_version": ">=6.0.0"
            }
        ]
    },
    
    
]


Nota: –json generará una lista plana de todos los paquetes con sus dependencias inmediatas. Para obtener JSON anidado, use – -json-tree (agregado en la versión 0.11.0).

Dominio:

$pipdeptree --json-tree

Producción:

 [
    {
        "key": "altair",
        "package_name": "altair",
        "installed_version": "4.1.0",
        "required_version": "4.1.0",
        "dependencies": [
            {
                "key": "entrypoints",
                "package_name": "entrypoints",
                "installed_version": "0.3",
                "required_version": "Any",
                "dependencies": []
            },
            {
                "key": "jinja2",
                "package_name": "jinja2",
                "installed_version": "2.11.2",
                "required_version": "Any",
                "dependencies": [
                    {
                        "key": "markupsafe",
                        "package_name": "MarkupSafe",
                        "installed_version": "1.1.1",
                        "required_version": ">=0.23",
                        "dependencies": []
                    }
                ]
            },
            
    {
        "key": "urllib3",
        "package_name": "urllib3",
        "installed_version": "1.25.9",
        "required_version": "1.25.9",
        "dependencies": []
    }
]

Publicación traducida automáticamente

Artículo escrito por nidhi_singh_ y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *