Dovrei mettere #! (shebang) negli script Python e quale forma dovrebbe assumere?


830

Devo mettere lo shebang nei miei script Python? In quale forma?

#!/usr/bin/env python 

o

#!/usr/local/bin/python

Sono ugualmente portatili? Quale forma viene utilizzata di più?

Nota: ilprogetto tornado utilizza lo shebang. D'altra parte ilprogetto Django no.


70
Il secondo non è portatile e sarà fallire su molti computer, se non la maggior parte.
Dietrich Epp,

4
Come si #!/usr/bin/pythonconfronta con la prima opzione? Vedo questo in parecchi esempi di codice. Edit: Forse questa è la risposta .. stackoverflow.com/a/2429517/1156245
geotheory


1
Dico sempre usarlo, perché? "Zen Of Python" - Linea 2 - "Esplicito è meglio che implicito." python.org/dev/peps/pep-0020
JayRizzo,

2
Francamente, nessuno dei due è "giusto", perché tu come autore non sai dove sarà la versione corretta di Python quando verrà eseguito lo script. Dovrebbe essere compito dell'installatore aggiungere lo shebang corretto.
Chepner,

Risposte:


1117

La riga shebang in qualsiasi script determina la capacità dello script di essere eseguito come un eseguibile autonomo senza digitare pythonprima nel terminale o facendo doppio clic su di esso in un file manager (se configurato correttamente). Non è necessario, ma generalmente viene messo lì, quindi quando qualcuno vede il file aperto in un editor, sa immediatamente cosa sta guardando. Tuttavia, quale linea shebang usi è importante.

L' uso corretto degli script Python 3 è:

#!/usr/bin/env python3

L'impostazione predefinita è 3.latest. Per Python 2.7.Ultimo utilizzo python2al posto di python3.

Non si deve usare quanto segue (ad eccezione del raro caso in cui si stia scrivendo codice compatibile con Python 2.xe 3.x):

#!/usr/bin/env python

La ragione di queste raccomandazioni, fornita in PEP 394 , è che pythonpuò fare riferimento python2ao python3su sistemi diversi. Attualmente fa riferimento alla python2maggior parte delle distribuzioni, ma è probabile che ad un certo punto cambierà.

Inoltre, NON utilizzare:

#!/usr/local/bin/python

"Python può essere installato in / usr / bin / python o / bin / python in questi casi, il precedente #! fallirà."

- "#! / usr / bin / env python" vs "#! / usr / local / bin / python"


4
@EliasVanOotegem Se non puoi essere sicuro che Python sarà trovato, /usr/binallora come puoi essere sicuro che envsarà trovato in /usr/bin. Se python è installato in un luogo non standard, probabilmente significa che python è configurato in un modo non standard e che di conseguenza lo script dovrebbe fallire rapidamente. Al contrario di fare ipotesi sulle proprietà dell'interprete Python e sperare nel meglio.
Dunes,

65
@Dunes: envsarà sempre trovato in /usr/bin/, e il suo compito è quello di individuare i bin (come Python) usando PATH. Indipendentemente da come è installato Python, il suo percorso verrà aggiunto a questa variabile e envlo troverà (in caso contrario, Python non è installato). Questo è il lavoro di env, questo è l'intero motivo per cui esiste. È la cosa che avvisa l'ambiente (imposta le variabili env, inclusi i percorsi di installazione e includi i percorsi). Le persone hanno sempre capito che questo comando può funzionare solo se si trova sempre nello stesso posto. Questo è solo un dato di fatto
Elias Van Ootegem il

3
@JFSebastian: hai ragione, non è garantito o applicato dallo standard POSIX. Supponevo che fosse perché una delle versioni successive di IEEE conteneva elementi ambientali. Ad ogni modo: no, /usr/bin/envnon è garantito da alcuno standard, a parte una regola ampiamente adottata (universalmente?) ...
Elias Van Ootegem,

6
Se stai usando virtualenv, #! / Usr / local / bin / python, anche se esiste, si sbaglia.
nullas

6
Un problema con questo: secondo PEP394 si dovrebbe usare l' pythoneseguibile solo quando lo script è compatibile con Python 2 e Python 3. Altrimenti, dovrebbe puntare alla scelta appropriata da python2e python3.
amiller27,

67

È davvero solo una questione di gusti. L'aggiunta di shebang significa che le persone possono invocare lo script direttamente se lo desiderano (supponendo che sia contrassegnato come eseguibile); ometterlo significa solo che pythondeve essere invocato manualmente.

Il risultato finale dell'esecuzione del programma non è influenzato in alcun modo; sono solo opzioni dei mezzi.


3
Questo è tutto - non importa da che parte stai perché non c'è un lato "giusto". È una decisione completamente soggettiva.
Ambra

5
Non più di qualsiasi altra decisione banale. en.wikipedia.org/wiki/Parkinson's_Law_of_Triviality
Amber

2
Come potrei eseguire un file Python direttamente senza il comando 'Python'?
Zen,

5
@Zen Supponendo che tu abbia incluso shebang (#! / Usr / bin / env python) nel tuo script devi solo rendere eseguibile il tuo script. Qualcosa del genere chmod a+x [your-script].pydovrebbe renderlo eseguibile e quindi puoi semplicemente chiamare ./[your-script.py]in shell.
skålfyfan,

9
Come la risposta GlassGhost fa notare, non v'è un vantaggio concreto per includerla oltre al gusto: si chiarisce a un lettore futuro del file che stanno leggendo uno script eseguibile, piuttosto che un file che è destinata ad essere importata. Analogamente ai modificatori di controllo dell'accesso pubblico / privato nelle lingue che li hanno, i shebang sono utili sia come documentazione che per il loro effetto reale e in alcuni casi l'aspetto della documentazione conta davvero.
Mark Amery,

32

Devo mettere lo shebang nei miei script Python?

Inserisci uno shebang in uno script Python per indicare:

  • questo modulo può essere eseguito come script
  • se può essere eseguito solo su python2, python3 o è compatibile con Python 2/3
  • su POSIX, è necessario se si desidera eseguire direttamente lo script senza richiamare pythonesplicitamente l'eseguibile

Sono ugualmente portatili? Quale forma viene utilizzata di più?

Se scrivi manualmente uno shebang, usa sempre a #!/usr/bin/env pythonmeno che tu non abbia un motivo specifico per non usarlo. Questo modulo è compreso anche su Windows (Python Launcher).

Nota: gli script installati devono utilizzare un eseguibile python specifico, ad esempio, /usr/bin/pythonoppure /home/me/.virtualenvs/project/bin/python. È male se qualche strumento si rompe se si attiva un virtualenv nella shell. Fortunatamente, lo shebang corretto viene creato automaticamente nella maggior parte dei casi dagli setuptoolsstrumenti del pacchetto di distribuzione (su Windows, è setuptoolspossibile generare .exeautomaticamente script wrapper ).

In altre parole, se lo script è in un checkout di origine, probabilmente vedrai #!/usr/bin/env python. Se è installato, allora shebang è un percorso di un eseguibile python specifico come #!/usr/local/bin/python (NOTA: non si devono scrivere manualmente i percorsi di quest'ultima categoria).

Per scegliere se utilizzare python, python2o python3nello shebang, vedere PEP 394 - Il comando "python" su sistemi simili a Unix :

  • ... pythondovrebbe essere usato nella riga shebang solo per script compatibili con sorgenti sia con Python 2 che con 3.

  • in preparazione di un'eventuale modifica della versione predefinita di Python, solo gli script di Python 2 devono essere aggiornati per essere compatibili con l'origine con Python 3 oppure da utilizzare python2nella riga shebang.


3
La prima risposta a riferirsi anche a un PEP non ha abbastanza voti. Eh? C'è un PEP per #!/usr/bin/env pythonse stesso?
binki,

Per favore, non usare #!/usr/bin/env python. Si prega di non suggerire di "usare sempre" #!/usr/bin/env python. Questa è la cosa sbagliata da fare nel 99% dei casi (il motivo che hai incluso nella tua risposta).
Jay Sullivan,

1
@JaySullivan capisci la differenza tra un checkout di origine e gli script installati? Sono dietro al suggerimento. Funziona bene.
jfs

1
@jfs: dopo aver riletto il mio commento, vedo come non sono riuscito a capire il mio punto. Intendevo dire che la maggior parte delle persone vorrà usare "python2" o "python3", non "python". Se risolvere o meno tramite il percorso completo o env, che tecnicamente era la domanda del PO, hai risposto e non sono d'accordo su questo punto.
Jay Sullivan,

@JaySullivan Sono d'accordo. Hai letto la citazione dal pep nella risposta. Dice la stessa cosa.
jfs,

15

Se hai più di una versione di Python e lo script deve essere eseguito con una versione specifica, she-bang può garantire che venga usata quella giusta quando lo script viene eseguito direttamente, ad esempio:

#!/usr/bin/python2.7

Nota che lo script potrebbe comunque essere eseguito tramite una riga di comando Python completa o tramite import, nel qual caso lo she-bang viene ignorato. Ma per gli script eseguiti direttamente, questa è una ragione decente per usare il botto.

#!/usr/bin/env python è generalmente l'approccio migliore, ma questo aiuta in casi speciali.

Di solito sarebbe meglio stabilire un ambiente virtuale Python, nel qual caso il generico #!/usr/bin/env pythonidentificherebbe l'istanza corretta di Python per virtualenv.


Lo spazio non lo farà fallire?
Casuale Insano,

1
@RandomInsano, io non la penso così. Gli spazi sembrano piuttosto comuni e ci sono molte prove intorno alla rete di questo come un uso accettato. Tuttavia, penso che il no-space sia probabilmente l'uso più canonico.
Chris Johnson,

1
Hai decisamente ragione su questo. Appena testato su bash e tcsh.
Casuale Insano

I risultati di whichti daranno una stringa che funzionerà, punto. Non devi preoccuparti di nessuna delle budella per usarla.
SDsolar,

10

Dovresti aggiungere uno shebang se lo script deve essere eseguibile. Dovresti anche installare lo script con un software di installazione che modifica lo shebang in qualcosa di corretto in modo che funzioni sulla piattaforma di destinazione. Esempi di questo sono distutils e Distribute.


1
Non è necessario modificare il #! linea dopo. Ecco a cosa serve / usr / bin / env. L'hard-coding su uno specifico interprete Python può fare più male che bene. È molto fragile riguardo all'installazione di un'altra versione di Python o al passaggio tra Python della nostra distribuzione e un'installazione Python personalizzata.
Vog

In Ubuntu, utilizzando i risultati di whichverrà automaticamente selezionato il valore predefinito utilizzato dai comandi di sistema e simili. È generico e il sistema lo dirige verso l'installazione corretta.
SDsolar,

9

Lo scopo di shebang è che lo script riconosca il tipo di interprete quando si desidera eseguire lo script dalla shell. Principalmente, e non sempre, esegui script fornendo l'interprete esternamente. Esempio di utilizzo:python-x.x script.py

Funzionerà anche se non hai un dichiaratore shebang.

Perché il primo è più "portatile" è perché, /usr/bin/envcontiene la tua PATHdichiarazione che rappresenta tutte le destinazioni in cui risiedono gli eseguibili del tuo sistema.

NOTA: Tornado non usa rigorosamente shebang e Django non lo fa rigorosamente. Dipende da come stai eseguendo la funzione principale dell'applicazione.

ANCHE: Non varia con Python.


8

A volte, se la risposta non è molto chiara (intendo che non puoi decidere se sì o no), allora non importa troppo e puoi ignorare il problema fino a quando la risposta non è chiara.

L' #!unico scopo è avviare la sceneggiatura. Django carica le fonti da solo e le usa. Non ha mai bisogno di decidere quale interprete dovrebbe essere usato. In questo modo, in #!realtà non ha senso qui.

In genere, se si tratta di un modulo e non può essere utilizzato come script, non è necessario utilizzare il #!. D'altra parte, una sorgente del modulo contiene spesso if __name__ == '__main__': ...almeno alcuni banali test della funzionalità. Quindi #!ha di nuovo senso.

Una buona ragione per l'uso #!è quando si usano sia gli script Python 2 che Python 3: devono essere interpretati da versioni diverse di Python. In questo modo, devi ricordare cosa pythondeve essere usato quando avvii lo script manualmente (senza l' #!interno). Se hai una combinazione di questi script, è una buona idea usare l' #!interno, renderli eseguibili e lanciarli come eseguibili (chmod ...).

Quando si utilizza MS-Windows, #!non aveva senso - fino a poco tempo fa. Python 3.3 introduce un Python Launcher di Windows (py.exe e pyw.exe) che legge la #!riga, rileva le versioni installate di Python e utilizza la versione corretta o esplicitamente desiderata di Python. Poiché l'estensione può essere associata a un programma, è possibile ottenere un comportamento simile in Windows come con il flag di esecuzione nei sistemi basati su Unix.


3

Quando di recente ho installato Python 3.6.1 su Windows 7, ha installato anche Python Launcher per Windows, che dovrebbe gestire la linea shebang. Tuttavia, ho scoperto che Python Launcher non lo faceva: la linea shebang veniva ignorata e veniva sempre usato Python 2.7.13 (a meno che non eseguissi lo script usando py -3).

Per risolvere questo problema, ho dovuto modificare la chiave di registro di Windows HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. Questo aveva ancora il valore

"C:\Python27\python.exe" "%1" %*

dalla mia precedente installazione di Python 2.7. Ho modificato questo valore della chiave di registro in

"C:\Windows\py.exe" "%1" %*

e l'elaborazione della linea shebang di Python Launcher ha funzionato come descritto sopra.


2

Se hai diversi moduli installati e devi utilizzare un'installazione specifica di Python, allora shebang sembra essere inizialmente limitato. Tuttavia, puoi fare trucchi come il seguente per consentire che shebang sia invocato prima come uno script di shell e quindi scegli python. Questo è molto flessibile imo:

#!/bin/sh
#
# Choose the python we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concat by python, shell ignores them
# c) "true" command ignores its arguments
# c) exit before the ending ''' so the shell reads no further
# d) reset set docstrings to ignore the multiline comment code
#
"true" '''\'
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3

if [ -x $PREFERRED_PYTHON ]; then
    echo Using preferred python $PREFERRED_PYTHON
    exec $PREFERRED_PYTHON "$0" "$@"
elif [ -x $ALTERNATIVE_PYTHON ]; then
    echo Using alternative python $ALTERNATIVE_PYTHON
    exec $ALTERNATIVE_PYTHON "$0" "$@"
else
    echo Using fallback python $FALLBACK_PYTHON
    exec python3 "$0" "$@"
fi
exit 127
'''

__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())

O meglio ancora, forse, per facilitare il riutilizzo del codice su più script Python:

#!/bin/bash
"true" '''\'; source $(cd $(dirname ${BASH_SOURCE[@]}) &>/dev/null && pwd)/select.sh; exec $CHOSEN_PYTHON "$0" "$@"; exit 127; '''

e quindi select.sh ha:

PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3

if [ -x $PREFERRED_PYTHON ]; then
    CHOSEN_PYTHON=$PREFERRED_PYTHON
elif [ -x $ALTERNATIVE_PYTHON ]; then
    CHOSEN_PYTHON=$ALTERNATIVE_PYTHON
else
    CHOSEN_PYTHON=$FALLBACK_PYTHON
fi

1
Anche se non sono sicuro che una poliglotta come questa sia una buona pratica in generale, è sicuramente un approccio molto interessante e probabilmente la risposta più flessibile qui.
Ryan Amos,

1
Molto bello. Non avevo capito che potresti farlo
user2233949

1

Risposta: solo se prevedi di renderlo uno script eseguibile da riga di comando.

Ecco la procedura:

Inizia verificando la stringa shebang corretta da usare:

which python

Prendi l'output da quello e aggiungilo (con shebang #!) Nella prima riga.

Sul mio sistema risponde così:

$which python
/usr/bin/python

Quindi il tuo shebang sarà simile a:

#!/usr/bin/python

Dopo il salvataggio, verrà comunque eseguito come prima poiché Python vedrà quella prima riga come commento.

python filename.py

Per renderlo un comando, copiarlo per eliminare l'estensione .py.

cp filename.py filename

Dire al file system che questo sarà eseguibile:

chmod +x filename

Per testarlo, utilizzare:

./filename

La migliore pratica è di spostarlo da qualche parte nel tuo $ PATH, quindi tutto ciò che devi digitare è il nome file stesso.

sudo cp filename /usr/sbin

In questo modo funzionerà ovunque (senza il ./ prima del nome del file)


Dubito che questa sia la migliore pratica e consiglio vivamente di utilizzare la soluzione GlassGhost .
Colidyre,

L'ho trovato utile e ha funzionato magnificamente per me. questo è stato ben spiegato. Gradirei commenti che indicano perché questa non è una buona pratica, tuttavia. Sono ansioso di imparare.
Charles Carriere,

0

Percorso assoluto vs logico:

Questa è davvero una domanda sul fatto che il percorso dell'interprete Python debba essere assoluto o logico ( /usr/bin/env) rispetto alla portabilità.

Incontrando altre risposte su questo e altri siti Stack che hanno parlato del problema in modo generale senza prove di supporto, ho eseguito alcuni test e analisi davvero, VERAMENTE , granulari su questa domanda su unix.stackexchange.com . Piuttosto che incollare la risposta qui, indicherò quelli interessati all'analisi comparativa a quella risposta:

https://unix.stackexchange.com/a/566019/334294

Essendo un ingegnere Linux, il mio obiettivo è sempre quello di fornire gli host più adatti e ottimizzati per i miei clienti sviluppatori, quindi il problema degli ambienti Python era qualcosa a cui avevo davvero bisogno di una risposta solida. Il mio punto di vista dopo il test era che il percorso logico nello she-bang era il migliore delle (2) opzioni.


-3

Usa prima

which python

Ciò fornirà l'output come posizione in cui è presente il mio interprete python (binario).

Questo output potrebbe essere qualsiasi

/usr/bin/python

o

/bin/python

Ora seleziona in modo appropriato la linea shebang e usala.

Per generalizzare possiamo usare:

#!/usr/bin/env

o

#!/bin/env

3
Molto probabilmente questo non sarà portatile per altri sistemi. #!/usr/bin/envfa la scelta giusta per te.
frammentedreality

Ecco perché usi il whichcomando: restituirà la stringa corretta per il tuo particolare sistema.
SDsolar,

1
... e poi ogni volta che lo script deve essere eseguito su un'altra macchina, esegui di which pythonnuovo e cambi lo script se l'output differisce dall'attuale shebang
fragmentedreality

2
-1 Questa è la soluzione più fragile possibile. È garantito che sia corretto solo per il sistema su cui è scritto il tuo script Python. Usa #! / Usr / bin / env python3 per la portabilità
Myles Hollowed
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.