stimmt nicht zwischen sys.executable und sys.version in Python

8

Es sind zwei Python-Interpreter installiert:

%Vor%

Sudo ändert PATH für jeden Befehl wie folgt:

%Vor%

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

    
Piotr Dobrogost 06.03.2014, 21:45
quelle

3 Antworten

5

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:

%Vor%

Py_GetProgramFullPath() function ist in der Datei Modules/getpath.c definiert, beginnend mit der Zeile 701 :

%Vor%

Die Funktion calcuate_path() ist in derselben Datei definiert und enthält den folgenden Kommentar :

%Vor%

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:

%Vor%

Es tut es.

Verwandte:

  • Python-Problem 7774 - sys.executable: falscher Speicherort, wenn das nullte Befehlsargument geändert wird.
  • Python-Problem 10835 - sys.executable default und altinstall
  • python-dev mailing list thread - hin zu einer strikteren Definition von sys .executable
  • Stackoverflow Frage - Wie finde ich den Speicherort der ausführbaren Datei in C
  • ?
Piotr Dobrogost 10.03.2014, 20:55
quelle
1

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.

Aktualisieren

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:

erstellen %Vor%

Dann führe es aus und hol ps , um dir die vollständigen Argumente zu geben:

%Vor%

Um auch sicher zu sein, welche python ausgeführt wird, können Sie Folgendes tun:

%Vor%

während das Programm läuft.

    
Graeme 06.03.2014 22:28
quelle
0

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:

  1. Installieren Sie die letzte Version von Python (gehen Sie auf die Website von Python, Downloade den letzten Code und configure && make && make install )
  2. Überprüfen Sie den Speicherort der letzten ausführbaren Version.
  3. Löschen Sie / usr / bin / python soft link ## (Sie benötigen root-Berechtigung sudo)
  4. ln -s <location der letzten ausführbaren Python-Version & gt; / usr / bin / python ## (ziemlich wahrscheinlich sudo benötigt)
  5. Führen Sie python über die Befehlszeile aus.
  6. importieren Sie sys

sys.version ## Es sollte die letzte sein.

    
Arturo Ruiz Mañas 14.01.2015 19:26
quelle

Tags und Links