Perché Python in Linux richiede la riga #! / Usr / bin / python?


50

Domanda piuttosto semplice: in Linux, perché Python richiede la linea

#!/usr/bin/python

all'inizio di un file Python, poiché Windows no?

Che cosa fa? perche 'la descrizione "Link a Python" è un po' vaga ...


28
Le risposte di seguito sono tutte corrette, nessuna di queste riguarda il motivo per cui Windows non necessita di questa riga. Windows dipende dall'estensione del file (la parte dopo il .) per determinare che tipo di file è. Anche Windows si sta allontanando da questo: esamina le prime righe del file di Microsoft Word e indicherà che in realtà è un file di Microsoft Word.
Charles Green,

9
L'elefante nella stanza è che non dovresti MAI usare / usr / bin / python a meno che tu non sia compatibile con Python 2 e 3. Motivo: arch lo collega a python3, una mossa riconosciuta dalla PSF, che lo sconsiglia.
Ancora un altro utente il

5
È implicito, ma non indicato esplicitamente nelle risposte sottostanti che non è richiesto . È necessario se si desidera eseguire lo script solo dal proprio nome. Puoi sempre correre python myscript.pyinvece.
Chris H,

3
@CharlesGreen non dovremmo sapere perché Windows non lo fa ;-) Dipende da SO.
Rinzwind,

2
@YetAnotherUser Sono passati sei anni e undici mesi da quando è stato rilasciato Python 3, a questo punto penso che le persone starebbero meglio a default 3 e specificare esplicitamente l'uso di 2 quando necessario.
JAB,

Risposte:


58

Python non ha tali requisiti speciali su Linux. È il caricatore di programmi su Unix / Linux che utilizza la linea "shebang", come viene chiamata. Questa è in realtà una caratteristica piuttosto che una limitazione, ma ci arriveremo tra un momento. La pagina Wiki su "shebang" ha più dettagli, ma cercherò di dare una panoramica e un confronto con Windows qui.

Innanzitutto, diamo un'occhiata alla situazione su Windows:

  • Quando si tenta di aprire o eseguire un file, Windows esamina innanzitutto l' estensione di quel file. Questa è l' ultima parte del nome del file che inizia con .Nel caso dei file Python, questo è in genere .py.
  • Windows cerca quale azione intraprendere in base all'estensione del file.
    • Questa informazione è registrata nel registro di Windows; quando viene installato Python, in genere indica a Windows che i .pyfile devono essere aperti utilizzando l' applicazione Python appena installata (ovvero l'interprete Python).
    • Diversi tipi di file hanno comportamenti incorporati; ad esempio, i file eseguibili (come l'interprete Python stesso) devono finire .exee i .batfile vengono eseguiti come script batch di Windows.
    • L'azione intrapresa per un determinato tipo di file è personalizzabile . Ad esempio, puoi dire a Windows che invece di eseguire i .pyfile utilizzando python.exe, dovrebbe aprirli con qualche altro programma, come l'editor di testo notepad.exe.
      • In questo caso, per eseguire uno script Python, devi chiamare manualmentepython <scriptname>.py (o scrivere un .batfile per farlo).

Ora, cosa succede se c'è una riga shebang ( #!/usr/bin/pythono #!/usr/bin/env python) nella parte superiore dello script Python? Bene, poiché #è una riga di commento in Python, l'interprete Python la ignora. Questo è uno dei motivi per cui la maggior parte dei linguaggi di scripting utilizzati nel mondo Unix / Linux usano #per iniziare le righe di commento.

Quindi è un po 'fuorviante dire che Windows "non ha bisogno" della #!linea; Windows non vede la #!linea e in effetti si basa sull'estensione del file per dirgli cosa fare. Questo ha un paio di svantaggi:

  • È necessario nominare gli script Python con .pyalla fine per farli riconoscere automaticamente come tali.
  • Non esiste un modo semplice per distinguere gli script Python2 dagli script Python3.
  • Come notato in precedenza, se si modifica il comportamento di avvio predefinito per il .pytipo di file, Windows non eseguirà più automaticamente quegli script con Python. Si noti che ciò potrebbe essere fatto involontariamente.

Ora diamo un'occhiata a come Unix / Linux lancia gli script:

La prima cosa da notare è che Unix / Linux, a differenza di Windows, non sta cercando di "aprire" gli script Python usando un particolare programma, almeno concettualmente; il sistema operativo sa che lo script è qualcosa che può essere eseguito a causa di qualcosa chiamato "bit di esecuzione" (che non rientra nell'ambito di questa risposta). Quindi, se si digita accidentalmente #!/usr/bin/pthonanziché #!/usr/bin/python, verrà visualizzato un messaggio di errore che include questo testo:

/usr/bin/pthon: bad interpreter: No such file or directory.

La parola "interprete" ci dà un indizio sul ruolo della linea shebang (anche se tecnicamente il programma specificato può essere qualcosa di diverso da un interprete, come cato un editor di testo). Quando si tenta di eseguire un file, ecco cosa succede:

  • Il caricatore del programma Unix / Linux esamina i primi due byte di quel file; se questi due byte lo sono #!, il caricatore interpreta il resto della riga shebang (escluso lo shebang stesso) come comando per avviare un interprete con cui eseguire il contenuto del file come script.
  • Il programma di caricamento programma avvia l'interprete specificato, fornendo come argomento il percorso del file originale.

Questo ha un paio di vantaggi:

  • Lo sceneggiatore ha un maggiore controllo su quale interprete verrà utilizzato (che risolve il problema Python2 / Python3) e talvolta può passare un ulteriore argomento all'interprete (vedere la pagina Wiki per i dettagli).
  • Il nome file dello script viene ignorato , quindi puoi nominare gli script Python come preferisci.

Nota, infine, che Unix / Linux non ha bisogno della linea shebang per eseguire uno script Python. Ricordiamo che tutta la linea shebang in realtà è consentire al caricatore di programmi di selezionare un interprete. Ma proprio come in Windows, questo può essere fatto manualmente:

python <myscript>

1
Su Windows potresti avere facilmente .py2ed .py3estensioni per gli script Python 2 / Python 3. Quindi sia Linux (+ x bit) che Windows (estensione file) hanno bisogno di metadati nel filesystem. La differenza principale è che il bit + x si perde più facilmente durante il trasporto. Questo non è necessariamente un aspetto negativo.
MSalters,

1
@MSalters Il bit di esecuzione ha anche molte meno informazioni codificate al suo interno. E nota che potresti avere più interpreti Python2 su un dato sistema (c'era una situazione simile con Ruby e altre lingue in un mio precedente lavoro); gestirlo tramite la linea shebang è quasi banale, mentre la situazione su Windows diventa sostanzialmente meno trattabile più si tenta di gestire più tipi di file simili.
Kyle Strand,

Inoltre, l'estensione conta davvero come "metadati"? Fa solo parte del nome del file.
Kyle Strand,

1
I metadati di un file includono l'intero nome file, il tempo di creazione, i bit di accesso, ecc. Solo il contenuto stesso è costituito da dati anziché da metadati. Per quanto riguarda i "interpreti multipli", questo è davvero un vero problema ed esattamente il motivo per cui non dovrebbe essere nella linea shebang. E se hai /usr/bin/i686/pythone /usr/bin/amd64/python? Perfettamente ragionevole, ma rompe gli script Python che hanno un presupposto hardcoded /usr/bin/python. La scelta dell'interprete non è una scelta dello sceneggiatore, ma dell'utente dello script. Lo sceneggiatore può solo scegliere la lingua (dialetto).
MSalters,

1
@MSalters Bene, ecco a cosa /usr/bin/envserve, insieme agli script env-setup. Qual è la versione Windows di questo? Esegui uno regeditscript subito prima di avviare un .pyfile per assicurarti di ottenere l'interprete che desideri?
Kyle Strand,

41

La riga che hai indicato viene utilizzata per indicare al computer quale programma / interprete utilizzare quando si esegue direttamente il file / script e tutti gli argomenti che devono essere passati a quel programma quando lo script viene eseguito. Questo non è, tuttavia, un requisito di Python , è un requisito del kernel / sistema di Linux se si intende eseguire direttamente lo script (e non passarlo a Python con la sintassi seguente).

Non è necessario se si intende eseguire python script.pyo simili. È necessario solo se si intende eseguire direttamente lo script / file, senza fornire anche l'interprete da utilizzare (come python).


Per uno script Bash, avrebbe qualcosa del genere:

#!/bin/bash [optional Bash arguments]
# Bash script code here
...
exit 0;

Ciò indicherebbe al sistema che, quando viene eseguito, dovrebbe essere eseguito tramite il /bin/bashquale è uno dei linguaggi shell / shell-script sul sistema.


Per il codice Python, tuttavia, qui vorrai far eseguire il file eseguibile tramite Python, quindi gli dirai quale interprete intendi averlo eseguito.

#!/usr/bin/python [optional Python arguments]
# Python code here
...
exit()

Questo, come per Bash, indica che /usr/bin/pythondovrebbe essere usato (questo è probabilmente Python 2 o Python 3, a seconda delle configurazioni del sistema individuale).


In questo modo, puoi eseguire ./filename.pyo ./executableo ./scripttorundirettamente.

Senza quella riga all'inizio, e supponendo che tu abbia impostato il file / script come eseguibile e supponendo che tu stia lavorando con uno script Python, dovresti eseguire python filename.pyo simili se non avessi la #!/usr/bin/pythonlinea. (Per uno script Bash, dovresti farlo bash script.sh, o simile per altri script / lingue, come Perl, Ruby, ecc.)

L'evidenziazione della sintassi sopra è specifica della lingua in ogni sezione, anche se non ha importanza.


1
Una cosa interessante da aggiungere è che è possibile specificare ulteriori parametri dopo la baracca in sé, nella maggior parte dei casi, nello stesso modo come se l'interprete è stato chiamato direttamente ( #!/bin/bash -x, #!/usr/bin/perl -lan, ecc).
kos,

7
@kos: Penso che puoi specificare esattamente un argomento in più, che è stato un PITA quando uno (dovrebbe) usare /usr/bin/env pythonper ottenere il pitone corretto.
unperson325680,

@progo Non sono sicuro di quale sia il problema env, ma il problema sembra non essere il numero di argomenti: #!/usr/bin/perl -l -a -nha tre argomenti ma funziona. Anche se di nuovo, non sono in grado di risolvere il problema esatto.
kos,

Quando si chiama esplicitamente un interprete con lo script come argomento, non vi è motivo di iniziare con quest'ultimo ./. In altre parole, solo python filename.pyo bash script.shfunzionerà bene. L'unico motivo per includere ./è nel nome di un comando, quando si desidera dire alla shell di non cercare $PATH(che probabilmente non troverà i file nella directory corrente) ma che segua il percorso specificato così com'è. Ma ciò non si applica agli argomenti dei comandi.
Marc van Leeuwen,

@kos: il problema potrebbe essere nel modo in cui envriceve il resto degli argomenti dal kernel. Si potrebbe presumere che si tratti di un grande argomento senza alcuna divisione per spazio eseguita. Mi dispiace per l'articolazione, non ricordo più bene i dettagli di questo
unperson325680

16

La linea:

#!/usr/bin/python

è chiamato "shebang" e indica il percorso del binario dell'interprete che verrà utilizzato per interpretare il resto dei comandi nel file. Di solito è la prima riga di una sceneggiatura.

Quindi la linea #!/usr/bin/pythonindica che il contenuto del file verrà interpretato dal pythonbinario situato in /usr/bin/python.

Nota che la riga di shebang viene analizzata dal kernel e quindi lo script verrà chiamato come argomento:

python script_name

Allo stesso modo in caso di #!/bin/bash:

bash script_name

2
Non credo di aver mai visto un trattino shebang. Poiché la parola è formata da "hash" e "bang", la tua ortografia non è molto chiara, poiché sembra che sia una combinazione di "lei" e "bang".
Kyle Strand,

Puoi chiamarlo hashbang( #= "hash") o shebang( #= "sharp"), a seconda di come assegni il #personaggio. Tuttavia, shebangè davvero più comune. @KyleStrand
Byte Commander

7

Tecnicamente, non lo richiede. Richiede un percorso per l'ambiente in cui viene eseguito lo script. I tuoi futuri script sarebbe meglio includere / usr / bin / env, quindi specificare python. Ciò garantisce che lo script venga eseguito nell'ambiente Python, indipendentemente da dove sia installato Python. Vuoi farlo per motivi di compatibilità, non puoi essere sicuro che la prossima persona con cui condividi il tuo codice avrà installato python in usr / bin / python o che disporrà delle autorizzazioni per quei file di sistema.

Ecco una domanda e risposta simile dall'overflow dello stack .

Quello che appare nella tua sceneggiatura è:

#!/usr/bin/env python

Vedo anche alcune preoccupazioni su come specificare python3. Ecco come farlo:

#!/usr/bin/env python3

5

In Linux, Python può o meno richiedere la #!linea (shebang). Questo dipende da come vengono gestiti i codici Python, eseguendo i codici in modalità interattiva Python o in uno script Python.

La modalità interattiva Python consente all'utente di digitare ed eseguire direttamente i codici Python, che non richiede la riga shebang. Per eseguire la modalità interattiva, aprire un Terminale e digitare pythonper Python 2.X o python3per Python 3.X.

$  python
Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

$  python3
Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Lo script Python consente all'utente di scrivere e salvare i codici Python in un file di testo semplice, quindi eseguire i codici in un secondo momento. Ciò può richiedere o meno la linea shebang. Tuttavia, ci sono due ragioni conosciute quando è richiesta la linea shebang per usare lo script Python in Linux.

  1. eseguire codici Python in uno script eseguibile, ad esempio definisce come devono essere eseguiti i codici e usando quale interprete;

  2. eseguire codici Python rispetto alla versione specifica di Python, ovvero eseguire codici compatibili solo con Python 2.X o Python 3.X

Esercitati con gli script Python

Di seguito è riportato l'elenco e il contenuto dei file, che ho usato per mostrare casi in cui la #!riga (shebang) è richiesta o non richiesta.

$  ls -ln *.py
-rw-rw-r-- 1 1000 1000  94 Dec 14 18:37 hello1.py
-rwxrwxr-x 1 1000 1000 116 Dec 14 18:37 hello2e.py
-rw-rw-r-- 1 1000 1000 116 Dec 14 18:37 hello2.py
-rwxrwxr-x 1 1000 1000 117 Dec 14 18:37 hello3e.py
-rwxrwxr-x 1 1000 1000 120 Dec 14 18:37 hello3m.py
-rw-rw-r-- 1 1000 1000 117 Dec 14 18:37 hello3.py

$  file *.py
hello1.py:  ASCII text
hello2e.py: Python script, ASCII text executable
hello2.py:  Python script, ASCII text executable
hello3e.py: Python script, ASCII text executable
hello3m.py: Python script, UTF-8 Unicode (with BOM) text executable
hello3.py:  Python script, ASCII text executable
  • hello1.py contiene solo codice sorgente.

    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
  • hello2.py contiene il codice sorgente e la riga shebang.

    #!/usr/bin/env python
    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
  • hello2e.pycontiene lo stesso hello2.pye reso eseguibile.

  • hello3.pycontiene lo stesso di hello2.py, tranne per il fatto che è adattato per funzionare con Python 3 rinominando la prima riga in #!/usr/bin/env python3.

  • hello3e.pycontiene lo stesso hello3.pye reso eseguibile.

  • hello3m.pycontiene lo stesso hello3.pye reso eseguibile, tranne che salvato con Write Unicode BOMopzione nell'editor di testo, ad esempio Mousepad.

Oltre a questo punto, all'utente verranno presentati due metodi per eseguire gli script Python. Entrambi i metodi sono stati dimostrati come di seguito.

Metodo 1: eseguire con il programma Python

Di seguito sono riportati i comandi e l'output durante l'esecuzione del codice sorgente con Python 2 e Python 3.

$  python hello1.py
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  python3 hello1.py
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

Entrambe le versioni di Python sono state in grado di eseguire correttamente lo script. Quindi, la riga shebang non è richiesta quando si esegue lo script Python tramite pythono python3comando.

Metodo 2: esegui come script Python

Di seguito sono riportati i comandi e l'output quando si esegue il codice sorgente con la riga shebang, che non sono adattati a nessuno dei due, Python 2 e Python 3, inclusi i casi non eseguibili ed eseguibili.

$  ./hello1.py
bash: ./hello1.py: Permission denied

$  ./hello2.py
bash: ./hello2.py: Permission denied

$  ./hello3.py
bash: ./hello3.py: Permission denied

$  ./hello2e.py 
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  ./hello3e.py 
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

I primi tre script hanno avuto esito negativo poiché questi script non sono eseguibili, indipendentemente dal fatto che abbiano o meno la riga shebang (per la dimostrazione di supporto, vedere l' esempio aggiuntivo di seguito). Gli ultimi due script hanno una riga shebang e sono eseguibili.

Apparentemente, una sceneggiatura che è stata resa eseguibile è essenzialmente inutile senza la linea shebang. Pertanto, è richiesta la riga shebang e lo script deve essere eseguibile quando si eseguono i codici Python in uno script eseguibile.

Quando shebang non funziona

Nel mio esempio preparato e testato, l'esecuzione hello3m.pycome script eseguibile non è riuscita e ha restituito un errore.

$  ./hello3m.py 
./hello3m.py: line 1: #!/usr/bin/env: No such file or directory

Questa è una limitazione nota che shebang non funziona o diventa non valida. Quando un file viene salvato come Unicode BOM (Byte Order Mark), non verrà eseguito normalmente come script Python eseguibile.

Esempio aggiuntivo

Questo esempio aggiuntivo deve essere considerato solo come prova a sostegno. L'utente dovrebbe evitare di eseguire questo esempio, sebbene il risultato sia innocuo.

Ho creato un altro file chiamato hello1e.py, che contiene lo stesso hello1.pye reso eseguibile. L'esecuzione di questo script ha restituito un errore di sintassi.

$  ./hello1e.py 
./hello1e.py: line 2: syntax error near unexpected token `"Hello from Python %s\n"'
./hello1e.py: line 2: `sys.stdout.write("Hello from Python %s\n" % (sys.version,))'

Quando si esegue questo script, inizialmente, il cursore del mouse verrà modificato in un segno più e non farà nulla in apparenza. L'errore di sintassi non verrà mostrato fino a quando non avrò fatto un clic sulla finestra Desktop o Terminale. Quindi, questo script creerà un sysfile nella stessa directory dello script.

$  file sys
sys: PostScript document text conforming DSC level 3.0, Level 1

Il sysfile è stato identificato come file PostScript, senza estensione. Questo file può essere aperto nel visualizzatore di documenti, ovvero Evince, e il file conteneva effettivamente uno screenshot della finestra su cui avevo fatto clic in precedenza. Nella mia esperienza, il file può essere grande quanto pochi Megabyte.

Ancora una volta, è richiesta la riga shebang e lo script deve essere eseguibile quando si esegue lo script Python come script eseguibile. Altrimenti, la sceneggiatura si comporterà come descritto sopra.

Note aggiuntive

Il termine "reso eseguibile" o "deve essere eseguibile" si riferisce all'autorizzazione per eseguire lo script. Questo viene eseguito eseguendo il chmod +x FILENAMEcomando in Terminale o selezionando l'opzione "Consenti a questo file di essere eseguito come programma" o qualcosa di simile nella finestra Proprietà , all'interno di un file manager.

Mentre altre risposte esistenti avevano riguardato quasi tutto, questa risposta ha adottato un approccio diverso usando esempi pratici per spiegare la questione. La sintassi del codice è stata scritta con cura, in modo tale che gli esempi possano essere eseguiti con Python 2 o Python 3, così com'è.

I codici Python sono stati adattati dall'uso di Python su Windows e dall'utilizzo di Python su piattaforme Unix , con il codice di una riga aggiuntivo dell'onnipresente "Hello, World!" programma.

Tutti i codici e i comandi sono stati completamente testati e funzionano nel sistema Xubuntu 14.04, con Python 2.7 e Python 3.4 installati per impostazione predefinita.


4

Significa che quando quel file viene eseguito il tuo computer sa eseguirlo con il programma /usr/bin/python, è così che lo dici a parte un'altra lingua, come bash dove lo faresti #!/bin/bash. Questo è così che puoi semplicemente eseguire:

./[file-to-execute]

E saprà con quale file eseguirlo, piuttosto che tu stesso devi specificare con qualcosa del tipo:

python ./[file-to-execute].py

La #!parte viene comunemente definita come una shebang o un botto crunch .


2
Anche un hashbang.
Naftuli Kay,

1

Se hai installato diverse versioni di Python, /usr/bin/envassicurati che l'interprete utilizzato sia il primo nel tuo ambiente $PATH. L'alternativa sarebbe codificare qualcosa del genere #!/usr/bin/python;

In Unix, un file eseguibile che deve essere interpretato può indicare quale interprete utilizzare avendo un #!all'inizio della prima riga, seguito dall'interprete (e da eventuali flag di cui potrebbe aver bisogno).

Questa regola è applicabile solo per il sistema basato su UNIX.


0

utile per sistemi operativi come Linux in cui Python 2.x è ancora lo standard, ma la maggior parte delle persone scarica anche 3.x.

2.x verrebbe eseguito di default. Quindi il mio codice 3.x, prefisso #! / Usr / bin / env python3 in modo che 3.x esegua il codice. Posso anche specificare fino alla revisione minore (python 3.xyz) se così ho scelto di avere versioni beta o solo versioni leggermente più vecchie.

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.