Soll ich # setzen! (shebang) in Python-Skripten, und welche Form sollte es annehmen?

829

Soll ich den Shebang in meine Python-Skripte einfügen? In welcher Form?

#!/usr/bin/env python 

oder

#!/usr/local/bin/python

Sind diese gleichermaßen tragbar? Welches Formular wird am häufigsten verwendet?

Hinweis: Das Tornado- Projekt verwendet den Shebang. Auf der anderen Seitetutdas Django- Projekt dies nicht.

Baumkodierer
quelle
70
Das zweite ist nicht tragbar und wird auf vielen Computern fehlschlagen, wenn nicht die meisten.
Dietrich Epp
4
Wie ist der #!/usr/bin/pythonVergleich mit der ersten Option? Ich sehe das in ziemlich vielen Beispielcodes. Bearbeiten: Vielleicht ist dies die Antwort .. stackoverflow.com/a/2429517/1156245
Geotheory
1
Ich sage immer benutze es, warum? "Zen Of Python" - Zeile 2 - "Explizit ist besser als implizit." python.org/dev/peps/pep-0020
JayRizzo
2
Ehrlich gesagt ist beides nicht "richtig", da Sie als Autor nicht wissen, wo sich die richtige Version von Python befindet, wenn das Skript ausgeführt wird. Es sollte die Aufgabe des Installateurs sein , den richtigen Shebang hinzuzufügen.
Chepper

Antworten:

1117

Die Shebang-Zeile in einem Skript bestimmt die Fähigkeit des Skripts, wie eine eigenständige ausführbare Datei ausgeführt zu werden, ohne pythonvorher in das Terminal einzugeben oder wenn Sie in einem Dateimanager darauf doppelklicken (bei ordnungsgemäßer Konfiguration). Es ist nicht notwendig, wird aber im Allgemeinen dort abgelegt. Wenn jemand die Datei in einem Editor geöffnet sieht, weiß er sofort, was er gerade sieht. Was jedoch shebang Linie , die Sie verwenden IS wichtig.

Die korrekte Verwendung für Python 3-Skripte lautet:

#!/usr/bin/env python3

Dies ist standardmäßig Version 3.latest. Für Python 2.7. Neueste Verwendung python2anstelle von python3.

Folgendes sollte NICHT verwendet werden (außer in dem seltenen Fall, dass Sie Code schreiben, der sowohl mit Python 2.x als auch mit 3.x kompatibel ist):

#!/usr/bin/env python

Der Grund für diese Empfehlungen in PEP 394 ist, dass pythonsie sich entweder auf python2oder python3auf verschiedenen Systemen beziehen können. Es bezieht sich derzeit auf die python2meisten Distributionen, aber das wird sich wahrscheinlich irgendwann ändern.

Verwenden Sie auch NICHT:

#!/usr/local/bin/python

"Python kann unter / usr / bin / python oder / bin / python installiert werden. In diesen Fällen schlägt das obige #! fehl."

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

GlassGhost
quelle
4
@EliasVanOotegem Wenn Sie sich nicht sicher sein , dass Python gefunden wird /usr/bindann , wie Sie sicher sein können , die envin gefunden werden /usr/bin. Wenn Python an einem nicht standardmäßigen Ort installiert wird, bedeutet dies wahrscheinlich, dass Python nicht standardmäßig eingerichtet wird und das Skript daher schnell fehlschlagen sollte. Im Gegensatz zu Annahmen über die Eigenschaften des Python-Interpreters und der Hoffnung auf das Beste.
Dunes
65
@Dunes: envwird immer in gefunden /usr/bin/, und seine Aufgabe ist es, Bins (wie Python) mit zu finden PATH. Unabhängig davon, wie Python installiert ist, wird der Pfad zu dieser Variablen hinzugefügt und envgefunden (andernfalls wird Python nicht installiert). Das ist die Aufgabe von env, das ist der ganze Grund, warum es existiert. Dies ist die Sache, die die Umgebung alarmiert (Env-Variablen einrichten, einschließlich der Installationspfade und Include-Pfade). Die Leute haben immer verstanden, dass dieser Befehl nur funktionieren kann, wenn er immer an derselben Stelle gefunden wird. Das ist nur eine
Selbstverständlichkeit
3
@JFSebastian: Sie haben Recht, es wird nicht garantiert oder durch den POSIX-Standard durchgesetzt. Ich nahm an, dass eine der späteren IEEE-Versionen einige Umgebungsdaten enthielt. So oder so: Nein, /usr/bin/envwird durch keinen anderen Standard als eine weit verbreitete (allgemein?) Angenommene Regel garantiert ...
Elias Van Ootegem
6
Wenn Sie virtualenv verwenden, wird #! / Usr / local / bin / python falsch, auch wenn es existiert.
Nullas
6
Ein Problem dabei: Laut PEP394 sollte man die pythonausführbare Datei nur verwenden, wenn das Skript mit Python 2 und Python 3 kompatibel ist. Andernfalls sollte es auf die entsprechende Auswahl von python2und verweisen python3.
Amiller27
67

Es ist wirklich nur eine Frage des Geschmacks. Durch Hinzufügen des Shebang können Benutzer das Skript direkt aufrufen, wenn sie möchten (vorausgesetzt, es ist als ausführbar markiert). Wenn Sie es weglassen, muss es nur pythonmanuell aufgerufen werden.

Das Endergebnis der Programmausführung wird in keiner Weise beeinflusst. es sind nur Optionen der Mittel.

Bernstein
quelle
3
Das ist es nur - es spielt keine Rolle, auf welcher Seite Sie stehen, denn es gibt keine "richtige" Seite. Es ist eine völlig subjektive Entscheidung.
Amber
5
Nicht mehr als jede andere triviale Entscheidung. en.wikipedia.org/wiki/Parkinson's_Law_of_Triviality
Amber
2
Wie kann ich eine Python-Datei direkt ohne den Befehl 'python' ausführen?
Zen
5
@Zen Angenommen, Sie haben den Shebang (#! / Usr / bin / env python) in Ihr Skript aufgenommen, müssen Sie Ihr Skript nur ausführbar machen. So etwas chmod a+x [your-script].pysollte es ausführbar machen und dann können Sie einfach die ./[your-script.py]Shell aufrufen .
Skålfyfan
9
Da die Antwort von GlassGhost darauf hinweist, es ist ein konkreter Vorteil es neben Geschmack einschließlich: es zu einem zukünftigen Leser der Datei klar macht , dass sie ein ausführbares Skript lesen, anstatt auf einer Datei , die importiert wird , ist gemeint. Ähnlich wie bei Modifikatoren für die öffentliche / private Zugriffskontrolle in Sprachen, in denen sie vorhanden sind, sind Shebangs sowohl als Dokumentation als auch für ihre tatsächliche Wirkung nützlich , und in einigen Fällen ist der Dokumentationsaspekt tatsächlich am wichtigsten.
Mark Amery
32

Soll ich den Shebang in meine Python-Skripte einfügen?

Fügen Sie einen Shebang in ein Python-Skript ein, um Folgendes anzuzeigen:

  • Dieses Modul kann als Skript ausgeführt werden
  • ob es nur auf python2, python3 ausgeführt werden kann oder ob es Python 2/3 kompatibel ist
  • Unter POSIX ist es erforderlich, wenn Sie das Skript direkt pythonausführen möchten, ohne die ausführbare Datei explizit aufzurufen

Sind diese gleichermaßen tragbar? Welches Formular wird am häufigsten verwendet?

Wenn Sie einen Shebang manuell schreiben, verwenden #!/usr/bin/env pythonSie ihn immer, es sei denn, Sie haben einen bestimmten Grund, ihn nicht zu verwenden. Dieses Formular wird auch unter Windows (Python Launcher) verstanden.

Hinweis: installierte Skripte sollte eine bestimmte Python ausführbare zB verwenden, /usr/bin/pythonoder /home/me/.virtualenvs/project/bin/python. Es ist schlecht, wenn ein Tool kaputt geht, wenn Sie eine virtuelle Umgebung in Ihrer Shell aktivieren. Glücklicherweise wird der richtige Shebang in den meisten Fällen automatisch von setuptoolsoder Ihren Distributionspaket-Tools erstellt (unter Windows setuptoolskönnen Wrapper- .exeSkripte automatisch generiert werden).

Mit anderen Worten, wenn sich das Skript in einer Quellkasse befindet, werden Sie wahrscheinlich sehen #!/usr/bin/env python. Wenn es installiert ist, ist der Shebang ein Pfad zu einer bestimmten ausführbaren Python-Datei wie #!/usr/local/bin/python (HINWEIS: Sie sollten die Pfade aus der letzteren Kategorie nicht manuell schreiben).

Zu entscheiden , ob Sie verwenden sollen python, python2oder python3in dem shebang finden PEP 394 - Der „Python“ Befehl auf Unix-ähnliche Systemen :

  • ... pythonsollte in der Shebang-Zeile nur für Skripte verwendet werden, die mit Python 2 und 3 quellkompatibel sind.

  • In Vorbereitung auf eine eventuelle Änderung der Standardversion von Python sollten nur Python 2-Skripte entweder aktualisiert werden, um mit Python 3 quellkompatibel zu sein, oder python2in der Shebang-Zeile verwendet werden.

jfs
quelle
3
Die erste Antwort, die sich überhaupt auf einen PEP bezieht, hat nicht genügend positive Stimmen. Huh? Gibt es einen PEP für #!/usr/bin/env pythonsich?
Binki
Bitte nicht benutzen #!/usr/bin/env python. Bitte schlagen Sie nicht vor, "immer zu verwenden" #!/usr/bin/env python. Dies ist in 99% der Fälle falsch (der Grund, den Sie in Ihre Antwort aufgenommen haben).
Jay Sullivan
1
@ JaySullivan Verstehst du den Unterschied zwischen einem Quell-Checkout und installierten Skripten? Ich stehe hinter dem Vorschlag. Es funktioniert gut.
JFS
1
@jfs: Nachdem ich meinen Kommentar noch einmal gelesen habe, sehe ich, dass ich meinen Standpunkt überhaupt nicht verstanden habe. Was ich damit meinte war, dass die meisten Leute 'python2' oder 'python3' verwenden wollen, nicht 'python'. Sie haben geantwortet, ob Sie über den vollständigen Pfad oder die Umgebung lösen möchten, was technisch gesehen die OP-Frage war, und ich bin in diesem Punkt nicht anderer Meinung.
Jay Sullivan
@ JaySullivan Ich stimme zu. Hast du das Zitat aus dem Pep in der Antwort gelesen? Es sagt dasselbe.
JFS
15

Wenn Sie mehr als eine Version von Python haben und das Skript unter einer bestimmten Version ausgeführt werden muss, kann der She-Bang sicherstellen, dass die richtige Version verwendet wird, wenn das Skript direkt ausgeführt wird, zum Beispiel:

#!/usr/bin/python2.7

Beachten Sie, dass das Skript weiterhin über eine vollständige Python-Befehlszeile oder über den Import ausgeführt werden kann. In diesem Fall wird der She-Bang ignoriert. Aber für Skripte, die direkt ausgeführt werden, ist dies ein guter Grund, den She-Bang zu verwenden.

#!/usr/bin/env python ist in der Regel der bessere Ansatz, aber dies hilft in besonderen Fällen.

Normalerweise ist es besser, eine virtuelle Python-Umgebung #!/usr/bin/env pythoneinzurichten. In diesem Fall identifiziert das Generikum die richtige Python-Instanz für die virtuelle Umgebung .

Chris Johnson
quelle
Wird der Raum nicht dazu führen, dass es versagt?
RandomInsano
1
@RandomInsano, das glaube ich nicht. Leerzeichen scheinen ziemlich häufig zu sein, und es gibt viele Beweise dafür, dass dies als akzeptierte Verwendung gilt. Ich denke jedoch, dass No-Space wahrscheinlich die kanonischere Verwendung ist.
Chris Johnson
1
Da hast du definitiv recht. Gerade auf bash und tcsh getestet.
RandomInsano
Die Ergebnisse von whichgeben Ihnen eine Zeichenfolge, die funktioniert, Punkt. Sie müssen sich keine Sorgen machen, um es zu benutzen.
SDsolar
10

Sie sollten einen Shebang hinzufügen, wenn das Skript ausführbar sein soll. Sie sollten das Skript auch mit einer Installationssoftware installieren, die den Shebang so ändert, dass er auf der Zielplattform funktioniert. Beispiele hierfür sind distutils und Distribute.

Lennart Regebro
quelle
1
Sie müssen das # nicht ändern! Linie danach. Dafür ist / usr / bin / env da. Hardcodierung gegen einen bestimmten Python-Interpreter kann mehr schaden als nützen. Es ist sehr fragil, eine andere Python-Version zu installieren oder zwischen Python unserer Distribution und einer benutzerdefinierten Python-Installation zu wechseln.
Vog
In Ubuntu wird unter Verwendung der Ergebnisse von whichautomatisch die Standardeinstellung ausgewählt, die von Systembefehlen und dergleichen verwendet wird. Es ist generisch und das System steuert es zur richtigen Installation.
SDsolar
9

Der Zweck von shebang besteht darin, dass das Skript den Interpretertyp erkennt, wenn Sie das Skript über die Shell ausführen möchten. Meistens und nicht immer führen Sie Skripte aus, indem Sie den Interpreter extern bereitstellen. Anwendungsbeispiel:python-x.x script.py

Dies funktioniert auch dann, wenn Sie keinen Shebang-Deklarator haben.

Der erste Grund ist, dass "portabler" ist, weil er /usr/bin/envIhre PATHDeklaration enthält, die alle Ziele berücksichtigt, an denen sich die ausführbaren Dateien Ihres Systems befinden.

HINWEIS: Tornado verwendet Shebangs nicht ausschließlich und Django nicht. Dies hängt davon ab, wie Sie die Hauptfunktion Ihrer Anwendung ausführen.

AUCH: Es variiert nicht mit Python.

meson10
quelle
8

Manchmal, wenn die Antwort ist nicht ganz klar (ich meine Sie nicht entscheiden können , ob ja oder nein), dann spielt es keine Rolle , zu viel, und man kann das Problem ignorieren , bis die Antwort ist klar.

Der #!einzige Zweck ist das Starten des Skripts. Django lädt die Quellen selbst und verwendet sie. Es muss nie entschieden werden, welcher Interpreter verwendet werden soll. Auf diese Weise #!macht das hier eigentlich keinen Sinn.

Wenn es sich um ein Modul handelt, das nicht als Skript verwendet werden kann, muss das im Allgemeinen nicht verwendet werden #!. Andererseits enthält eine Modulquelle häufig if __name__ == '__main__': ...zumindest einige triviale Tests der Funktionalität. Dann #!macht das wieder Sinn.

Ein guter Grund für die Verwendung #!ist, wenn Sie sowohl Python 2- als auch Python 3-Skripte verwenden - diese müssen von verschiedenen Versionen von Python interpretiert werden. Auf diese Weise müssen Sie sich merken, was pythonbeim manuellen Starten des Skripts (ohne das #!Innere) verwendet werden muss. Wenn Sie eine Mischung solcher Skripte haben, ist es eine gute Idee, das #!Innere zu verwenden, sie ausführbar zu machen und sie als ausführbare Dateien zu starten (chmod ...).

Bei der Verwendung von MS-Windows hatte das #!keinen Sinn - bis vor kurzem. Python 3.3 führt einen Windows Python Launcher (py.exe und pyw.exe) ein, der die #!Zeile liest , die installierten Versionen von Python erkennt und die richtige oder explizit gewünschte Version von Python verwendet. Da die Erweiterung einem Programm zugeordnet werden kann, können Sie unter Windows ein ähnliches Verhalten wie mit dem Ausführungsflag in Unix-basierten Systemen erzielen.

pepr
quelle
3

Als ich kürzlich Python 3.6.1 unter Windows 7 installiert habe, wurde auch der Python Launcher für Windows installiert, der die Shebang-Zeile verarbeiten soll. Ich stellte jedoch fest, dass der Python Launcher dies nicht tat: Die Shebang-Zeile wurde ignoriert und Python 2.7.13 wurde immer verwendet (es sei denn, ich habe das Skript mit py -3 ausgeführt).

Um dies zu beheben, musste ich den Windows-Registrierungsschlüssel bearbeiten HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. Dies hatte immer noch den Wert

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

von meiner früheren Python 2.7-Installation. Ich habe diesen Registrierungsschlüsselwert in geändert

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

und die Python Launcher Shebang-Linienverarbeitung funktionierte wie oben beschrieben.

ETalbot
quelle
2

Wenn Sie verschiedene Module installiert haben und eine bestimmte Python-Installation verwenden müssen, scheint shebang zunächst eingeschränkt zu sein. Sie können jedoch Tricks wie die folgenden ausführen, damit der Shebang zuerst als Shell-Skript aufgerufen und dann Python ausgewählt werden kann. Das ist sehr flexibel 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())

Oder noch besser, um die Wiederverwendung von Code über mehrere Python-Skripte hinweg zu erleichtern:

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

und dann select.sh hat:

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
Neil McGill
quelle
1
Ich bin mir zwar nicht sicher, ob ein Polyglott wie dieser im Allgemeinen eine gute Praxis ist, aber es ist sicherlich ein sehr interessanter Ansatz und wahrscheinlich die flexibelste Antwort hier.
Ryan Amos
1
Sehr cool. Ich wusste nicht, dass du das
kannst
1

Antwort: Nur wenn Sie vorhaben, daraus ein ausführbares Befehlszeilenskript zu machen.

Hier ist die Vorgehensweise:

Überprüfen Sie zunächst die richtige Shebang-Zeichenfolge:

which python

Nehmen Sie die Ausgabe davon und fügen Sie sie (mit der shebang #!) In die erste Zeile ein.

Auf meinem System reagiert es wie folgt:

$which python
/usr/bin/python

Ihr Schebang wird also so aussehen:

#!/usr/bin/python

Nach dem Speichern wird es weiterhin wie zuvor ausgeführt, da Python diese erste Zeile als Kommentar sieht.

python filename.py

Um daraus einen Befehl zu machen, kopieren Sie ihn, um die Erweiterung .py zu löschen.

cp filename.py filename

Teilen Sie dem Dateisystem mit, dass dies ausführbar sein wird:

chmod +x filename

Verwenden Sie zum Testen Folgendes:

./filename

Die beste Vorgehensweise besteht darin, es irgendwo in Ihrem $ PATH zu verschieben, sodass Sie nur den Dateinamen selbst eingeben müssen.

sudo cp filename /usr/sbin

Auf diese Weise funktioniert es überall (ohne das ./ vor dem Dateinamen)

SDsolar
quelle
Ich bezweifle, dass dies eine bewährte Methode ist, und empfehle dringend die Verwendung der GlassGhost-Lösung .
Colidyre
Ich fand das hilfreich und es hat wunderbar für mich funktioniert. das wurde gut erklärt. Ich würde mich über Kommentare freuen, die darauf hinweisen, warum dies jedoch keine bewährte Methode ist. Ich bin gespannt zu lernen.
Charles Carriere
0

Absoluter vs logischer Pfad:

Dies ist wirklich eine Frage, ob der Pfad zum Python-Interpreter in Bezug auf die Portabilität absolut oder logisch ( /usr/bin/env) sein sollte.

Als ich auf dieser und anderen Stack-Sites auf andere Antworten stieß, die allgemein über das Problem sprachen, ohne Beweise zu unterstützen, habe ich auf unix.stackexchange.com einige wirklich WIRKLICH granulare Tests und Analysen zu dieser Frage durchgeführt . Anstatt diese Antwort hier einzufügen, werde ich diejenigen, die an der vergleichenden Analyse interessiert sind, auf diese Antwort verweisen:

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

Als Linux-Ingenieur ist es immer mein Ziel, meinen Entwickler-Clients die am besten geeigneten, optimierten Hosts bereitzustellen. Daher war das Problem der Python-Umgebungen etwas, auf das ich wirklich eine solide Antwort brauchte. Nach dem Testen war ich der Ansicht, dass der logische Pfad im She-Bang die bessere der (2) Optionen war.

F1Linux
quelle
-3

Zuerst verwenden

which python

Dies gibt die Ausgabe als den Ort an, an dem mein Python-Interpreter (binär) vorhanden ist.

Diese Ausgabe kann eine beliebige sein

/usr/bin/python

oder

/bin/python

Wählen Sie nun die Shebang-Linie entsprechend aus und verwenden Sie sie.

Zur Verallgemeinerung können wir verwenden:

#!/usr/bin/env

oder

#!/bin/env
frp farhan
quelle
3
Dies wird höchstwahrscheinlich nicht auf andere Systeme portierbar sein. #!/usr/bin/envtrifft die richtige Wahl für Sie.
Fragmentierte
Aus diesem Grund verwenden Sie den whichBefehl - er gibt die richtige Zeichenfolge für Ihr bestimmtes System zurück.
SDsolar
1
... und dann jedes Mal, wenn das Skript auf einem anderen Computer ausgeführt werden soll, führen Sie es which pythonerneut aus und ändern das Skript, wenn die Ausgabe vom aktuellen Shebang abweicht
fragmentierte
2
-1 Dies ist die fragilste mögliche Lösung. Es ist garantiert nur für das System korrekt, auf dem Ihr Python-Skript geschrieben ist. Verwenden Sie #! / Usr / bin / env python3 für die Portabilität
Myles Hollowed