Es sind zwei Python-Interpreter installiert:
%Vor% Sudo ändert PATH
für jeden Befehl wie folgt:
Ich führe ein Testskript aus:
%Vor% und erhalte den Pfad zu Python 2.4.3 in sys.executable
und Version 2.7.6 in sys.version
. Offensichtlich stimmen sys.executable
und sys.version
nicht überein. Unter Berücksichtigung, wie sudo PATH modifiziert, kann ich den Wert von sys.executable
verstehen. Warum meldet sys.version
jedoch Version 2.7.6 und nicht Version 2.4.3, die dem von usr/bin/python
? Berichteten sys.executable
Pfad entsprechen?
Dies ist ein Follow-up zu meiner Frage. Sudo ändert PATH, führt aber die gleiche Binärdatei aus
Beide @Graeme
Die Tatsache, dass Python dies möglicherweise nicht abrufen kann, weist darauf hin, dass dies der Fall ist macht eine eigene PATH-Suche (...)
und @twalberg
(...) Es sieht so aus, als ob sys.executable den aktuellen PATH durchsucht Auflösen von argv [0] (oder vielleicht, weil argv [0] in diesem Fall simpy python ist Fall ...), (...)
hatte grundsätzlich recht. Ich wollte nicht glauben, dass Python etwas so Einfaches (dummes?) Tut, als ob er PATH
benutzt, um sich selbst zu lokalisieren, aber das ist wahr.
Pythons sys
Modul ist in Python/sysmodule.c
Datei implementiert. Ab Version 2.7.6 wird sys.executable
in Zeile 1422 eingestellt das:
Py_GetProgramFullPath()
function ist in der Datei Modules/getpath.c
definiert, beginnend mit der Zeile 701 :
Die Funktion calcuate_path()
ist in derselben Datei definiert und enthält den folgenden Kommentar :
Wie in meinem Fall zu sehen ist, verliert man auch, wenn das erste Python auf exportierten $PATH
anders ist als das Python, das ausgeführt wird.
Weitere Informationen zur Berechnung der Platzierung der ausführbaren Datei des Interpreters finden Sie unter oben von getpath.c
file:
Bevor irgendwelche Suchen durchgeführt werden, ist der Speicherort der ausführbaren Datei entschlossen. Wenn argv [0] einen oder mehrere Schrägstriche enthält, wird es verwendet unverändert. Andernfalls muss es vom Pfad der Shell aufgerufen worden sein, Also suchen wir $ PATH für die benannte ausführbare Datei und verwenden diese. Wenn die Die ausführbare Datei wurde nicht in $ PATH gefunden (oder es gab keine $ PATH-Umgebung) Variable), die ursprüngliche argv [0] Zeichenfolge wird verwendet.
Als nächstes wird der ausführbare Ort untersucht, um zu sehen, ob es ein Symbol ist Verknüpfung. Wenn dies der Fall ist, wird der Link gejagt (einen Verwandten korrekt interpretieren) Pfadname wenn einer gefunden wird) und das Verzeichnis des Linkziels wird verwendet.
Machen wir ein paar Tests, um das oben genannte zu überprüfen:
Wenn argv [0] einen oder mehrere Schrägstriche enthält, wird es unverändert verwendet.
%Vor%Ok.
Wenn die ausführbare Datei nicht in $ PATH gefunden wurde (oder es keine Umgebungsvariable $ PATH gab), wird die ursprüngliche argv [0] Zeichenfolge verwendet.
%Vor%Falsch. In diesem Fall ist die Aussage aus der Dokumentation des sys-Moduls wahr - Wenn Python das Reale nicht abrufen kann Pfad zu seiner ausführbaren Datei, sys.executable wird eine leere Zeichenfolge oder None sein. .
Schauen wir uns an, ob der Ort der Python-Binärdatei wieder zu PATH
hinzugefügt wird (nachdem sudo ihn entfernt hat) korrigiert das Problem:
Es tut es.
Verwandte:
Ich denke /usr/local/bin/python
ist die ausführbare Datei, die gerade läuft. Der Versions-String wird fast sicher in python
kompiliert, daher ist es sehr unwahrscheinlich, dass er falsch ist. Schauen Sie sich die Dokumentation für sys.executable
an:
sys.executable
Eine Zeichenfolge, die den absoluten Pfad der ausführbaren Binärdatei für den Python-Interpreter angibt, auf Systemen, auf die dies sinnvoll ist. Wenn Python den echten Pfad zu seiner ausführbaren Datei nicht finden kann, wird sys.executable eine leere Zeichenfolge oder None sein.
Die Tatsache, dass python
dies möglicherweise nicht abrufen kann, deutet darauf hin, dass es seine eigene PATH
Suche unter Verwendung von PATH
sudo durchführt (was laut meiner Antwort auf die vorherige Frage nicht dasselbe ist wie die eine, die es verwendet, um die ausführbare Datei zu finden).
Der einzige Weg, hier sicher zu sein, ist die Python-Implementierung zu durchforsten, aber generell würde ich sagen, dass der Versions-String eher der ist, dem Sie vertrauen können. Auf der anderen Seite verwendet sudo
execve
, um den Befehl auszuführen (zumindest entsprechend der Seite man
). Sie müssen den vollständigen Pfad der ausführbaren Datei zu execve
angeben (einige der exec
-Varianten haben ihre eigene PATH
-Suche, diese nicht). Daher sollte es kein Kinderspiel sein, python
in sys.executable
einzufügen.
Ich weiß nicht, ob es eine Möglichkeit gibt, das argv[0]
für den python
Interpreter zu bekommen ( sys.argv[0]
ist immer der Name des Skripts oder -c
), aber das wäre interessant zu sehen . Wenn es /usr/local/bin/python
ist, wäre dies ein Fehler in python
.
Ich denke, das Beste ist, nur secure_path
in /etc/sudoers
zu setzen, hoffentlich erhalten Sie dann eine gewisse Konsistenz.
Tatsächlich nimmt execve
ein Argument für den ausführbaren Pfad und dann ein argv
-Array an, also ist argv[0]
nicht unbedingt /usr/local/bin/python
. Sie können es jedoch immer noch herausfinden, indem Sie ein Skript wie:
Dann führe es aus und hol ps
, um dir die vollständigen Argumente zu geben:
Um auch sicher zu sein, welche python
ausgeführt wird, können Sie Folgendes tun:
während das Programm läuft.
Jedes Mal, wenn Sie den Python-Interpreter starten, geht die Shell zu / usr / bin / python und führt sie aus (versuchen Sie es als nächstes: python -c "import os; print (os.environ ['_'])").
Nun, wie Sie sehen können, ist ln -l | grep python
/ usr / bin / python eine Soft-Link zur ausführbaren Datei des Python-Interpreters.
Was ich getan habe, war:
configure && make && make install
) ln -s <location
der letzten ausführbaren Python-Version & gt; / usr / bin / python
## (ziemlich wahrscheinlich sudo benötigt) sys.version ## Es sollte die letzte sein.