Diagnosticare i conflitti tra dipendenze Python con pip e virtualenv

by theArchitect
SHARE
Diagnosticare i conflitti tra dipendenze Python con pip e virtualenv
© Guida-HTML5.it

Introduzione

Quando un progetto Python cresce, può dipendere da numerosi pacchetti indiretti. Un’applicazione potrebbe installare requests, mentre un altro componente richiede una versione diversa di una libreria usata internamente da requests. Questo tipo di situazione può causare errori durante l’installazione o, ancora peggio, problemi soltanto a runtime.

In questo tutorial vedremo un approccio pratico per analizzare e risolvere i conflitti tra dipendenze usando pip e virtualenv. L’obiettivo non è soltanto installare pacchetti, ma capire quali versioni sono presenti, verificare se sono compatibili e separare correttamente l’ambiente di analisi dal sistema operativo.

Utilizzeremo anche il comando pip check, particolarmente utile per individuare dipendenze mancanti o versioni incompatibili. Questo strumento è semplice, ma spesso viene trascurato durante il debugging.

Codice completo

Creiamo una piccola procedura automatizzabile. Il file seguente prepara un ambiente virtuale, installa alcuni pacchetti di esempio e verifica la coerenza delle dipendenze.

# crea un ambiente virtuale nella cartella .venv
python -m virtualenv .venv

# attiva l´ambiente su Linux o macOS
source .venv/bin/activate

# Su Windows PowerShell usare:
# .venvScriptsActivate.ps1

# Aggiorna gli strumenti di packaging
python -m pip install --upgrade pip setuptools wheel

# Installa alcune dipendenze di esempio
python -m pip install requests flask

# Mostra i pacchetti installati nell´ambiente corrente
python -m pip list

# Visualizza informazioni dettagliate su un pacchetto
python -m pip show requests

# Controlla eventuali dipendenze mancanti o incompatibili
python -m pip check

# Genera un elenco utile per una successiva analisi
python -m pip freeze > installed-packages.txt

# Esci dall´ambiente virtuale quando hai terminato
deactivate

È possibile aggiungere un controllo automatico a uno script Python. In questo modo la verifica può essere eseguita in una pipeline CI oppure prima di creare un pacchetto di distribuzione.

from __future__ import annotations

import subprocess
import sys


def verifica_dipendenze() -> int:
    """Esegue pip check usando lo stesso interprete Python del progetto."""
    risultato = subprocess.run(
        [sys.executable, "-m", "pip", "check"],
        capture_output=True,
        text=True,
        check=False,
    )

    if risultato.returncode == 0:
        print("Dipendenze coerenti: nessun problema rilevato.")
        return 0

    print("Sono stati rilevati problemi nelle dipendenze:")
    print(risultato.stdout or risultato.stderr)
    return risultato.returncode


if __name__ == "__main__":
    raise SystemExit(verifica_dipendenze())

Spiegazione

Perché usare un ambiente isolato

virtualenv crea una directory contenente un interprete Python e gli strumenti necessari per installare pacchetti separatamente dal sistema. In questo modo, un esperimento con una versione specifica di una libreria non modifica gli altri progetti presenti sul computer.

Il comando python -m virtualenv .venv usa il modulo virtualenv come programma Python. La directory .venv è una convenzione molto diffusa e dovrebbe essere esclusa dal controllo versione tramite .gitignore.

# .gitignore
.venv/
__pycache__/
*.pyc

Perché preferire python -m pip

Su un computer possono essere installate più versioni di Python. Il comando pip potrebbe riferirsi a un interprete diverso da quello usato per avviare il progetto. Usando python -m pip, invece, chiediamo esplicitamente all’interprete attivo di eseguire pip.

Questa forma riduce errori come: “ho installato il pacchetto, ma Python non lo trova”. Se l’ambiente virtuale è attivo, anche python punterà all’interprete corretto.

Come leggere pip check

pip check controlla i metadati dei pacchetti installati e segnala due categorie principali di problemi:

  • una dipendenza richiesta da un pacchetto non è installata;
  • la versione installata non soddisfa il vincolo dichiarato.

Un risultato simile a package X requires Y>=2.0, but you have Y 1.5 indica un conflitto. In quel caso bisogna capire quale pacchetto richiede la versione più recente e se l’aggiornamento può rompere il codice esistente.

Analizzare la causa del conflitto

Per indagare è utile combinare diversi comandi:

# Elenco ordinato dei pacchetti installati
python -m pip list

# Dettagli del pacchetto, inclusi i requisiti
python -m pip show nome-pacchetto

# Informazioni dell´ambiente e della versione di pip
python -m pip --version
python --version

# Simula un´installazione senza modificare l´ambiente
python -m pip install --dry-run nome-pacchetto

L’opzione --dry-run è preziosa perché permette di vedere quali pacchetti pip sceglierebbe senza installarli realmente. È utile prima di aggiornamenti importanti o quando si sospetta che una nuova versione introduca incompatibilità.

Best practice

  • Usa un ambiente virtuale per ogni progetto. Evita di condividere globalmente pacchetti tra applicazioni diverse.
  • Esegui sempre pip tramite l’interprete Python attivo. Preferisci python -m pip a un comando pip ambiguo.
  • Controlla l’ambiente dopo le installazioni. Esegui python -m pip check come verifica finale.
  • Non risolvere i conflitti alla cieca. Prima di aggiornare una libreria, controlla i requisiti dei pacchetti dipendenti.
  • Usa installazioni conservative in produzione. Testa gli aggiornamenti in un ambiente separato prima di applicarli al sistema reale.
  • Documenta la versione di Python. Una dipendenza può essere compatibile con Python 3.11 ma non con Python 3.9.
  • Automatizza i controlli. Lo script Python mostrato può essere eseguito in CI e trasformare un conflitto in un errore immediatamente visibile.

È inoltre consigliabile esaminare periodicamente i pacchetti inutilizzati. Un progetto con molte dipendenze superflue aumenta la probabilità di conflitti e rende più difficile individuare l’origine di un problema.

Riepilogo

La gestione delle dipendenze non consiste soltanto nell’eseguire pip install. Un metodo affidabile prevede la creazione di un ambiente isolato con virtualenv, l’uso coerente di python -m pip, l’analisi dei pacchetti installati e la verifica finale con pip check.

Quando compare un conflitto, è utile procedere gradualmente: identificare il pacchetto coinvolto, leggere i requisiti dichiarati, simulare l’installazione con --dry-run e testare la soluzione in un ambiente separato. Questa pratica riduce gli errori e rende il progetto più semplice da mantenere.

Approfondisci con risorse ufficiali

SHARE