Su Ubuntu 20.04 LTS la scelta corretta non è “installare Python 2.7 di sistema”, ma tenerlo isolato. Il motivo è semplice: il sistema base e molti pacchetti moderni si aspettano Python 3, quindi forzare Python 2 a livello globale crea più danni che benefici. Se hai ancora un’app legacy che richiede Python 2.7 e pip2, la strada pulita è usare un runtime separato, con dipendenze dedicate e un perimetro chiaro.
In pratica ci sono due scenari sensati: usare pyenv per compilare e gestire Python 2.7 in home directory, oppure creare un ambiente controllato in un container o in una VM. Qui resto sul caso più comune per un server Ubuntu 20.04: installazione locale con pyenv, così non tocchi il Python di sistema e puoi rimuovere tutto senza lasciare residui critici.
Perché non installare Python 2.7 nel sistema base
Ubuntu 20.04 include Python 3 come riferimento operativo. Python 2 è fuori manutenzione da anni, quindi i repository standard non lo trattano come componente supportato del sistema. Il rischio non è solo “tecnico” ma operativo: un upgrade futuro, un pacchetto che punta a /usr/bin/python, o uno script di manutenzione che eredita il PATH sbagliato possono rompere servizi essenziali.
Se un vecchio applicativo chiede Python 2.7, la domanda giusta non è come renderlo globale, ma come contenerlo. L’obiettivo è avere un binario python2.7 e un comando pip2 disponibili solo dove servono, senza alterare /usr/bin/python3 né i symlink del sistema.
Approccio consigliato: pyenv per Python 2.7 isolato
Classifica operativa: change controllato. Stato atteso: un host Ubuntu 20.04 che deve eseguire un’app legacy con Python 2.7 e installare moduli con pip2, senza cambiare il runtime di sistema. Stato osservato tipico: Python 2 non presente, oppure presente solo in qualche vecchio ambiente, con errori del tipo python2: command not found o pip2: command not found.
Le ipotesi più probabili sono tre:
Python 2.7 non è installato affatto: lo falsifichi con python2.7 --version o pyenv versions in meno di 5 minuti.
Python 2.7 esiste ma non c’è pip2: lo falsifichi con python2.7 -m pip --version.
Il problema è nel PATH o nell’ambiente shell: lo falsifichi con which python2.7 e echo $PATH.
Prima di modificare qualcosa, conviene verificare il layer giusto: non stai risolvendo un guasto di sistema, stai preparando un runtime legacy. Quindi il blast radius deve restare limitato alla home dell’utente o a un account di servizio dedicato.
Prerequisiti minimi sul server
Per compilare Python 2.7 con pyenv servono alcune librerie di build. Su Ubuntu 20.04 puoi installare i pacchetti base con apt. Questo tocca solo dipendenze di compilazione e non cambia il runtime di sistema.
Se il server è di produzione, conviene fare un checkpoint minimo: snapshot della VM o backup del profilo utente che ospiterà pyenv. Il rollback in questo caso è semplice: rimuovi la directory di pyenv e le righe aggiunte al profilo shell.
sudo apt update
sudo apt install -y \
make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev \
curl llvm libncursesw5-dev xz-utils tk-dev \
libxml2-dev libxmlsec1-dev libffi-dev liblzma-devSe il comando fallisce per pacchetti mancanti, non andare a tentativi: controlla il repository configurato e lo stato di apt update. L’evidenza minima è l’output di apt-cache policy libssl-dev oppure il messaggio d’errore di apt install.
Installazione di pyenv
Installa pyenv nell’account che eseguirà l’applicazione legacy. Evita root salvo casi molto specifici. L’installazione seguente usa la home dell’utente corrente.
curl https://pyenv.run | bashQuesto script scarica i componenti necessari in ~/.pyenv. Dopo il completamento, aggiungi le variabili d’ambiente alla shell. In ~/.bashrc o ~/.profile inserisci:
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"Poi ricarica il profilo:
source ~/.bashrcVerifica che pyenv sia attivo:
pyenv --version
pyenv rootAtteso: versione di pyenv e percorso sotto /home/<utente>/.pyenv. Se invece il comando non è trovato, il problema è nel PATH e non nella compilazione di Python.
Installare Python 2.7.18 con pyenv
La release finale della serie 2.7 è 2.7.18. È quella da usare se devi mantenere compatibilità con script storici ma vuoi l’ultima build disponibile della linea 2.7.
pyenv install 2.7.18La compilazione può richiedere alcuni minuti. Se fallisce, la causa più comune è una libreria di sviluppo mancante o una incompatibilità del toolchain. In quel caso l’evidenza utile è il log completo dell’installazione, non il messaggio finale in sintesi. Se serve, riesegui con verbosità maggiore:
PYENV_DEBUG=1 pyenv install 2.7.18Una volta completata l’installazione, imposta la versione per la shell corrente o per una directory specifica. Per un uso locale e controllato è meglio il file .python-version nel progetto.
pyenv local 2.7.18
python --versionAtteso: Python 2.7.18. In alternativa puoi usare pyenv global 2.7.18, ma solo se sai esattamente che quell’utente deve usare Python 2 come default nelle sue sessioni. Su server condivisi è una scelta più fragile.
Come ottenere pip2 senza sporcare il sistema
Con Python 2.7 installato via pyenv, in molti casi pip è già disponibile tramite python -m pip. Se non c’è, il metodo corretto è installarlo con get-pip.py per Python 2.7, sempre nell’ambiente isolato.
Prima verifica lo stato attuale:
python -m pip --version
python -m ensurepip --versionSe pip non è presente o non funziona, scarica lo script compatibile con Python 2.7 e usalo solo all’interno dell’ambiente pyenv. Non eseguire procedure che scrivono sotto /usr su Ubuntu 20.04.
curl -O https://bootstrap.pypa.io/pip/2.7/get-pip.py
python get-pip.pyDopo l’installazione, verifica:
python -m pip --version
pip --versionSe ti serve proprio il nome pip2, puoi creare un alias di shell, ma è preferibile usare il binario richiamato dal PATH dell’ambiente oppure python -m pip. Un alias è comodo, ma non è un confine di sicurezza. Se vuoi un comando esplicito, in alcuni casi pyenv espone pip puntato al Python attivo; in altri conviene usare direttamente python -m pip per evitare ambiguità.
Esempio pratico: installare un modulo legacy
Supponiamo di dover installare una versione vecchia di Flask o un driver che supporta ancora Python 2. Con il runtime isolato, il flusso resta prevedibile:
pyenv local 2.7.18
python -m pip install --upgrade pip==20.3.4
python -m pip install requests==2.27.1Qui c’è un punto importante: l’ultima linea di compatibilità pratica per Python 2 è molto vecchia. Se un pacchetto recente non si installa, non è un bug del server; è il limite della piattaforma. In quel caso la verifica utile è il messaggio di incompatibilità di pip, non la reinstallazione di Python.
Un dettaglio operativo spesso ignorato: se l’app legacy ha anche dipendenze native, potresti dover installare header e librerie specifiche per quella singola app, non per Python in generale. L’evidenza da guardare è l’errore di compilazione del modulo, che di solito cita il file header mancante o la libreria non trovata.
Integrazione con servizi systemd o script di avvio
Se il Python 2.7 deve essere usato da un servizio systemd, non affidarti a una shell interattiva. Devi puntare al binario esplicito di pyenv oppure caricare correttamente l’ambiente del servizio. La soluzione più robusta è usare il path assoluto del Python installato da pyenv.
~/.pyenv/versions/2.7.18/bin/pythonNel file unit puoi definire qualcosa del genere, adattando utente e percorso applicativo:
[Service]
User=appuser
WorkingDirectory=/srv/legacy-app
ExecStart=/home/appuser/.pyenv/versions/2.7.18/bin/python /srv/legacy-app/app.pyDopo ogni modifica al service file:
sudo systemctl daemon-reload
sudo systemctl restart legacy-app.service
sudo systemctl status legacy-app.serviceSe il servizio non parte, controlla journalctl -u legacy-app.service -b. Il problema di solito è uno tra: path errato, permessi sul venv o sulla home dell’utente, oppure variabili d’ambiente mancanti. Il rollback, in questo caso, è tornare alla vecchia unit o allo snapshot del file in /etc/systemd/system/.
Alternative da valutare prima di fermarsi su Python 2
Se stai facendo questo lavoro su un server esposto, vale la pena fermarsi un attimo e chiedersi se l’app può essere migrata. Python 2.7 non riceve più correzioni di sicurezza, quindi ogni nuovo modulo aggiunge debito tecnico e superficie d’attacco. Il rischio non è teorico: librerie vecchie, dipendenze non aggiornate e tool di packaging obsoleti aumentano la probabilità di incompatibilità e vulnerabilità.
Se la migrazione non è possibile subito, almeno limita il contesto: utente dedicato, directory dedicata, porte non esposte pubblicamente senza reverse proxy, e dipendenze bloccate in un ambiente riproducibile. In molti casi un container con immagine congelata è più pulito di un runtime legacy sparso nell’host.
Checklist di verifica finale
pyenv versions mostra 2.7.18 come attiva nel progetto.
python --version restituisce Python 2.7.18 nel contesto desiderato.
python -m pip --version funziona senza errori di import o di SSL.
L’app legacy parte con il binario esplicito di pyenv o con il service systemd aggiornato.
Il sistema globale resta invariato: /usr/bin/python3 e i pacchetti di Ubuntu non sono stati toccati.
Assunzione operativa: l’obiettivo è mantenere Python 2.7 solo per compatibilità temporanea, non costruire una nuova base applicativa su tecnologia fuori supporto.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.