Frage Warum schreiben Leute den #! / Usr / bin / env Python Shebang in die erste Zeile eines Python-Skripts?


Es scheint mir so, als würden die Dateien ohne diese Zeile gleich laufen.


820
2018-03-11 23:50


Ursprung


Antworten:


Wenn Sie mehrere Versionen von Python installiert haben, /usr/bin/env stellt sicher, dass der verwendete Interpreter der erste auf Ihrer Umgebung ist $PATH. Die Alternative wäre, etwas wie hart zu codieren #!/usr/bin/python; das ist in Ordnung, aber weniger flexibel.

In Unix, ein ausführbar Die Datei, die interpretiert werden soll, kann angeben, welcher Interpreter verwendet werden soll #! am Anfang der ersten Zeile, gefolgt vom Interpreter (und allen eventuell benötigten Flags).

Wenn Sie über andere Plattformen sprechen, gilt diese Regel natürlich nicht (aber "shebang line" schadet nicht und hilft Ihnen, wenn Sie dieses Skript jemals auf eine Plattform kopieren mit eine Unix-Basis wie Linux, Mac usw.).


902
2018-03-11 23:52



Das nennt man das Shebang-Linie. Als die Wikipedia-Eintrag erklärt:

In der Informatik bezieht sich ein Shebang (auch Hashbang, Haschling, Pfundknall oder Knirschen genannt) auf die Zeichen "#!" wenn es sich bei den ersten beiden Zeichen in einer Interpreter-Anweisung um die erste Zeile einer Textdatei handelt. In einem Unix-ähnlichen Betriebssystem nimmt der Programmlader das Vorhandensein dieser zwei Zeichen als ein Anzeichen dafür, dass die Datei ein Skript ist, und versucht, dieses Skript unter Verwendung des durch den Rest der ersten Zeile in der Datei spezifizierten Interpretierers auszuführen.

Siehe auch die Unix-FAQ-Eintrag.

Selbst unter Windows, wo die Shebang-Zeile nicht bestimmt, welcher Interpreter ausgeführt werden soll, können Sie Optionen an den Interpreter übergeben, indem Sie sie in der Shebang-Zeile angeben. Ich finde es nützlich, eine generische Shebang-Zeile in einmaligen Skripten zu behalten (wie diejenigen, die ich schreibe, wenn ich Fragen zu SO beantworte), damit ich sie schnell unter Windows und Windows XP testen kann ArchLinux.

Das env-Dienstprogramm Ermöglicht Ihnen, einen Befehl auf dem Pfad aufzurufen:

Das erste verbleibende Argument gibt den aufzurufenden Programmnamen an. es wird nach dem gesucht PATH Umgebungsvariable. Alle verbleibenden Argumente werden als Argumente an dieses Programm übergeben.


222
2018-03-11 23:52



Erweitern Sie ein wenig die anderen Antworten, hier ist ein kleines Beispiel dafür, wie Ihre Kommandozeilenskripte durch unvorsichtigen Einsatz von /usr/bin/env Schlangenlinien:

$ /usr/local/bin/python -V
Python 2.6.4
$ /usr/bin/python -V
Python 2.5.1
$ cat my_script.py 
#!/usr/bin/env python
import json
print "hello, json"
$ PATH=/usr/local/bin:/usr/bin
$ ./my_script.py 
hello, json
$ PATH=/usr/bin:/usr/local/bin
$ ./my_script.py 
Traceback (most recent call last):
  File "./my_script.py", line 2, in <module>
    import json
ImportError: No module named json

Das JSON-Modul existiert in Python 2.5 nicht.

Eine Möglichkeit, sich vor diesem Problem zu schützen, ist die Verwendung der Versionsnamen von Python-Befehlen, die normalerweise bei den meisten Pythons installiert sind:

$ cat my_script.py 
#!/usr/bin/env python2.6
import json
print "hello, json"

Wenn Sie nur zwischen Python 2.x und Python 3.x unterscheiden müssen, bieten aktuelle Versionen von Python 3 auch eine python3 Name:

$ cat my_script.py 
#!/usr/bin/env python3
import json
print("hello, json")

135
2018-03-12 00:35



Um das Python-Skript auszuführen, müssen wir der Shell drei Dinge sagen:

  1. Dass die Datei ein Skript ist
  2. Welchen Interpreter möchten wir das Skript ausführen?
  3. Der Weg des besagten Dolmetschers

Der Shebang #! vollbringt (1.). Der Shebang beginnt mit einem # weil das #character ist ein Kommentarmarker in vielen Skriptsprachen. Der Inhalt der Shebang-Zeile wird daher vom Interpreter automatisch ignoriert.

Das env Befehl führt (2.) und (3.) aus. Um "Grawity" zu zitieren

Eine häufige Verwendung der env Befehl ist, Dolmetscher zu starten, indem Sie   Verwendung der Tatsache, dass env $ PATH nach dem Befehl sucht, der ihm mitgeteilt wird   starten. Da die Shebang-Linie einen absoluten Pfad benötigt, ist sie   spezifiziert, und seit dem Ort der verschiedenen Dolmetscher (Perl, Bash,   Python) kann sehr variieren, es ist üblich zu verwenden:

#!/usr/bin/env perlanstatt zu raten, ob es ist   / bin / perl, / usr / bin / perl, / usr / lokal / bin / perl, / usr / local / pkg / perl,   / fileserver / usr / bin / perl, oder / home / MrDaniel / usr / bin / perl auf dem Benutzer   System...

Auf der anderen Seite ist env fast immer in / usr / bin / env. (Außer in   Fälle, wenn es nicht ist; Einige Systeme verwenden möglicherweise / bin / env, aber das ist a   ziemlich seltene Gelegenheit und passiert nur auf Nicht-Linux-Systemen.)


78
2018-03-26 00:07



In Python ist dies nur eine Kommentarzeile.

Diese Zeile wird nur verwendet, wenn Sie das py-Skript ausführen aus der Schale (von der Befehlszeile). Dies ist bekannt als das "Shebang! "und es wird in verschiedenen Situationen verwendet, nicht nur mit Python-Skripten.

Hier wird die Shell angewiesen, a zu starten spezifische Version von Python (um den Rest der Datei zu kümmern.


38
2018-03-11 23:58



Vielleicht ist Ihre Frage in diesem Sinne:

Wenn Sie Folgendes verwenden möchten: $python myscript.py

Sie brauchen diese Zeile überhaupt nicht. Das System ruft Python auf und der Python-Interpreter führt Ihr Skript aus.

Aber wenn Sie beabsichtigen zu verwenden: $./myscript.py

Wenn Sie es direkt wie ein normales Programm oder Bash-Skript aufrufen, müssen Sie diese Zeile schreiben, um dem System mitzuteilen, welches Programm es benutzt, und es mit ausführbar machen chmod 755)


37
2018-01-17 11:13



Der Hauptgrund dafür besteht darin, das Skript in Betriebssystemumgebungen portierbar zu machen.

Zum Beispiel verwenden Python-Skripte unter mingw:

#!/c/python3k/python 

und unter GNU / Linux-Distribution ist es entweder:

#!/usr/local/bin/python 

oder

#!/usr/bin/python

und unter dem besten kommerziellen Unix sw / hw System von allen (OS / X) ist es:

#!/Applications/MacPython 2.5/python

oder auf FreeBSD:

#!/usr/local/bin/python

Alle diese Unterschiede können jedoch das Skript über alle portierbar machen:

#!/usr/bin/env python

34
2017-07-20 22:34



Das exec Systemaufruf des Linux-Kerns versteht Shebangs (#!) nativ

Wenn Sie auf bash machen:

./something

Unter Linux ruft dies die exec Systemaufruf mit dem Pfad ./something.

Diese Zeile des Kernels wird für die übergebene Datei aufgerufen exec: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm-> buf [0]! = '#') || (bprm-> buf [1]! = '!'))

Dies liest die ersten Bytes der Datei und vergleicht sie mit #!.

Wenn das stimmt, wird der Rest der Zeile vom Linux-Kernel analysiert, der einen anderen Exec-Aufruf mit Pfad ausführt /usr/bin/env python und aktuelle Datei als erstes Argument:

/usr/bin/env python /path/to/script.py

und das funktioniert für jede Skriptsprache, die verwendet wird # als Kommentarzeichen.

Und ja, Sie können eine unendliche Schleife machen mit:

#!/a

und eine ausführbare Datei an /a

#! ist einfach menschlich lesbar, aber das ist nicht erforderlich.

Wenn die Datei mit verschiedenen Bytes gestartet wurde, dann wird die exec Systemaufruf würde einen anderen Handler verwenden. Der andere wichtigste integrierte Handler ist für ausführbare ELF-Dateien: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 welches auf Bytes prüft 7f 45 4c 46 (was zufällig auch für Menschen lesbar ist) .ELF). Dies liest die ELF-Datei, legt sie korrekt in den Speicher und startet damit einen neuen Prozess. Siehe auch: Wie erhält der Kernel eine ausführbare Binärdatei, die unter Linux läuft?

Schließlich können Sie Ihre eigenen Shebang Handler mit hinzufügen binfmt_misc Mechanismus. Zum Beispiel können Sie ein hinzufügen benutzerdefinierter Handler für .jar Dateien. Dieser Mechanismus unterstützt sogar Handler durch Dateierweiterung. Eine andere Anwendung ist es Transparente Ausführung von ausführbaren Dateien einer anderen Architektur mit QEMU.

Ich glaube nicht, dass POSIX Shebangs spezifiziert: https://unix.stackexchange.com/a/346214/32558 , obwohl es in rationalen Abschnitten erwähnt, und in der Form "wenn ausführbare Skripts vom System unterstützt werden, kann etwas passieren".


23
2017-12-02 18:29