Distribuzione di Python e portabilità di /usr/bin/env
-
09-06-2019 - |
Domanda
All'inizio di tutti i miei script Python eseguibili inserisco il file shebang linea:
#!/usr/bin/env python
Sto eseguendo questi script su un sistema in cui env python
produce un ambiente Python 2.2.I miei script falliscono rapidamente perché ho un controllo manuale per una versione Python compatibile:
if sys.version_info < (2, 4):
raise ImportError("Cannot run with Python version < 2.4")
Non voglio dover modificare la riga Shebang su ogni file eseguibile, se possibile;tuttavia, non ho accesso amministrativo alla macchina per modificare il risultato env python
e non voglio forzare una versione particolare, come in:
#!/usr/bin/env python2.4
Vorrei evitarlo perché il sistema potrebbe avere una versione più recente di Python 2.4 o potrebbe avere Python 2.5 ma non Python 2.4.
Qual è la soluzione elegante?
[Modifica:] Non sono stato abbastanza specifico nel porre la domanda: vorrei consentire agli utenti di eseguire gli script senza configurazione manuale (ad es.alterazione del percorso o collegamento simbolico ~/bin
e assicurandoti che il tuo PERCORSO abbia ~/bin
prima del percorso Python 2.2).Forse è necessaria qualche utilità di distribuzione per impedire le modifiche manuali?
Soluzione
"env" esegue semplicemente la prima cosa che trova nel PATH env var.Per passare a un Python diverso, anteponi la directory dell'eseguibile di quel Python al percorso prima di invocare lo script.
Altri suggerimenti
Soluzione piuttosto hacker: se il controllo fallisce, usa questa funzione (che probabilmente potrebbe essere notevolmente migliorata) per determinare il miglior interprete disponibile, determinare se è accettabile e, in tal caso, riavviare lo script con os.system o qualcosa di simile e il tuo sys. argv utilizzando il nuovo interprete.
import os
import glob
def best_python():
plist = []
for i in os.getenv("PATH").split(":"):
for j in glob.glob(os.path.join(i, "python2.[0-9]")):
plist.append(os.path.join(i, j))
plist.sort()
plist.reverse()
if len(plist) == 0: return None
return plist[0]
Se stai eseguendo gli script, puoi impostare la variabile PATH in modo che punti prima a una directory bin privata:
$ mkdir ~/bin
$ ln -s `which python2.4` ~/bin/python
$ export PATH=~/bin:$PATH
Quindi quando esegui lo script Python utilizzerà Python 2.4.Dovrai modificare i tuoi script di accesso per cambiare il tuo PERCORSO.
In alternativa esegui il tuo script Python con l'interprete esplicito che desideri:
$ /path/to/python2.4 <your script>
@morais:È un'idea interessante, ma penso che forse possiamo fare un ulteriore passo avanti.Forse c'è un modo per usarlo Il virtualenv di Ian Bicking A:
- Per cominciare, verifica se stiamo correndo in un ambiente accettabile e, in tal caso, non fare nulla.
- Controlla se esiste un eseguibile specifico della versione su
PATH
, cioè.controlla sepython2.x
esistefor x in reverse(range(4, 10))
.In tal caso, rieseguire il comando con l'interprete migliore. - Se non esiste un interprete migliore, usa virtualenv per provare a installare una versione più recente di Python dalla versione precedente di Python e ottenere eventuali pacchetti prerequisiti.
Non ho idea se virtualenv sia in grado di farlo, quindi presto ci proverò.:)
Ecco una soluzione se sei (1) assolutamente determinato a utilizzare shebangs e (2) in grado di utilizzare Autotools nel processo di creazione.
Ieri sera ho scoperto che puoi usare la macro autoconf AM_PATH_PYTHON
per trovare un Python minimo 2 binario.La procedura è Qui.
Quindi, il tuo processo sarebbe:
- Emettere un
AM_PATH_PYTHON(2.4)
nel tuoconfigure.ac
- Rinomina tutti i tuoi
.py
script a.py.in
(secondo la mia esperienza, questo non crea confusionevi
) - Dai un nome a tutti gli script Python con cui vuoi generare
AC_CONFIG_FILES
. - Invece di iniziare con
#!/usr/bin/env python
, utilizzo#!@PYTHON@
Allora il tuo risultante Gli script Python avranno sempre uno shebang appropriato.
Quindi, hai questa soluzione, almeno possibile, se non pratica.