Introduzione
Quando lavori su più progetti Python, il problema più comune non è scrivere il codice, ma mantenere ogni progetto coerente nel tempo. Una libreria aggiornata in un progetto può rompere un altro progetto che si aspetta una versione diversa. Per evitare questi conflitti, la soluzione più pratica è usare ambienti virtuali con virtualenv e installare le dipendenze con pip.
In questo tutorial vedremo un sotto-argomento molto utile e spesso sottovalutato: come verificare, riprodurre e pulire un ambiente Python in modo affidabile. Non ci limiteremo a creare l’ambiente, ma impareremo a controllare cosa è installato, come esportare le dipendenze in modo ripetibile e come mantenere il progetto pulito nel tempo.
Questo approccio è fondamentale in team, in progetti professionali e anche nei piccoli script personali, perché riduce gli errori “sul mio computer funziona” e rende il progetto molto più facile da condividere.
Codice completo
#!/usr/bin/env python3
"""
Esempio pratico: creare un ambiente virtuale, installare dipendenze,
verificare le versioni e generare un elenco riproducibile.
"""
import subprocess
import sys
from pathlib import Path
PROJECT_DIR = Path("demo_progetto")
VENV_DIR = PROJECT_DIR / ".venv"
REQUIREMENTS_FILE = PROJECT_DIR / "requirements.txt"
def run(cmd):
"""Esegue un comando di shell e interrompe il programma in caso di errore."""
print(f"n$ {´ ´.join(cmd)}")
subprocess.run(cmd, check=True)
def create_project_structure():
"""Crea una cartella di progetto minimale."""
PROJECT_DIR.mkdir(exist_ok=True)
print(f"Cartella progetto: {PROJECT_DIR.resolve()}")
def create_virtualenv():
"""Crea un ambiente virtuale isolato."""
run([sys.executable, "-m", "virtualenv", str(VENV_DIR)])
def install_packages():
"""Installa pacchetti utili per l´esempio."""
pip = VENV_DIR / "bin" / "pip"
run([str(pip), "install", "requests==2.32.3", "python-dotenv==1.0.1"])
def show_installed_packages():
"""Mostra i pacchetti installati nell´ambiente."""
pip = VENV_DIR / "bin" / "pip"
run([str(pip), "list"])
def export_requirements():
"""Salva le dipendenze esatte in requirements.txt."""
pip = VENV_DIR / "bin" / "pip"
with REQUIREMENTS_FILE.open("w", encoding="utf-8") as f:
subprocess.run([str(pip), "freeze"], check=True, stdout=f)
print(f"Creato file: {REQUIREMENTS_FILE.resolve()}")
def main():
create_project_structure()
create_virtualenv()
install_packages()
show_installed_packages()
export_requirements()
print("nAmbiente pronto e dipendenze esportate.")
if __name__ == "__main__":
main()
Spiegazione
Il codice mostra un flusso di lavoro realistico. Prima crea una cartella di progetto, poi genera un ambiente virtuale nella directory .venv. Questa scelta è molto comune perché tiene l’ambiente vicino al progetto, ma separato dal Python di sistema.
La funzione create_virtualenv() usa python -m virtualenv per creare l’ambiente. In alternativa, su molte installazioni moderne puoi usare anche python -m venv. Tuttavia, virtualenv resta molto utile quando vuoi più flessibilità o compatibilità con vecchi workflow.
La funzione install_packages() installa due librerie con versioni bloccate:
- requests==2.32.3 per fare richieste HTTP in modo semplice;
- python-dotenv==1.0.1 per caricare configurazioni da file .env.
Bloccare le versioni è importante perché evita sorprese nei rilasci. Se oggi il progetto funziona con una certa versione, domani vuoi poter ricreare lo stesso comportamento.
La funzione show_installed_packages() usa pip list per controllare cosa c’è installato davvero nell’ambiente. Questo passaggio è utile per diagnosticare problemi, ad esempio se un pacchetto è presente ma in una versione diversa da quella prevista.
Infine, export_requirements() usa pip freeze per salvare l’elenco completo delle dipendenze in requirements.txt. Questo file è fondamentale per riprodurre l’ambiente su un’altra macchina o in CI/CD. In pratica, consente di dire: “installa esattamente ciò che ho io adesso”.
Un flusso tipico di utilizzo, dopo aver creato l’ambiente, è questo:
- attivare l’ambiente virtuale;
- installare le librerie necessarie;
- testare l’applicazione;
- esportare le dipendenze con pip freeze;
- condividere requirements.txt con il team.
Su Linux e macOS l’attivazione avviene spesso con:
source .venv/bin/activate Su Windows, invece, il comando è generalmente:
.venvScriptsactivate Una volta attivo, ogni installazione con pip rimane confinata all’ambiente virtuale. Questo è il punto chiave: non stai alterando il Python globale della macchina, ma solo il progetto corrente.
Best practice
- Usa sempre un ambiente virtuale per progetto: evita conflitti tra librerie di app diverse.
- Versiona requirements.txt: il file va tenuto nel repository, così il progetto è riproducibile.
- Non installare pacchetti globalmente per lavorare su progetti: è una delle cause più frequenti di problemi difficili da diagnosticare.
- Blocca le versioni critiche: per librerie sensibili o in produzione, specifica versioni precise.
- Controlla periodicamente le dipendenze: usa pip list e pip freeze per verificare cosa è davvero installato.
- Separa dipendenze runtime e sviluppo: ad esempio, test, lint e tool di formattazione possono stare in un file dedicato o in gruppi separati.
- Ricrea l’ambiente da zero quando hai dubbi: è spesso più veloce che cercare di “riparare” un ambiente sporco.
Un consiglio pratico: se il progetto cresce, evita di affidarti solo a una lista generica di pacchetti. Documenta anche il comando esatto usato per creare l’ambiente e, se possibile, automatizza la procedura con uno script o un Makefile. Questo riduce gli errori manuali e migliora la collaborazione.
Riepilogo
Gestire le dipendenze con pip e virtualenv non significa solo installare librerie: significa costruire un ambiente coerente, isolato e riproducibile. Il punto più importante è separare il progetto dal sistema operativo, così ogni applicazione può usare le versioni di cui ha davvero bisogno.
In questo tutorial abbiamo visto un flusso pratico: creare un ambiente virtuale, installare pacchetti con versioni precise, controllare l’elenco delle dipendenze e salvare tutto in requirements.txt. Questo è un ottimo punto di partenza per progetti piccoli e medi, ma anche una base solida per workflow più avanzati.
Se applichi con costanza queste abitudini, ridurrai moltissimo i problemi di compatibilità e renderai il tuo codice più facile da distribuire, testare e mantenere.
Approfondisci con risorse ufficiali
- pip documentation: guida ufficiale per installazione e gestione pacchetti.
- virtualenv documentation: documentazione ufficiale per ambienti virtuali avanzati.
- Python Packaging User Guide: risorsa autorevole per packaging e dependency management.
- PEP 405: specifica degli ambienti virtuali integrati in Python.
- PEP 508: sintassi dei requirement e dei marker di ambiente.
Se vuoi, nel prossimo passo posso scrivere un tutorial complementare su come separare dipendenze di sviluppo e produzione con pip e requirements.txt, con un esempio completo e pronto da usare.
