Python subprocess Popen umgebung PATH?

Ich bin verwirrt darüber, wie subprocess bei der Verwendung von Popen() nach der ausführbaren Datei sucht. Es funktioniert, wenn es absolute Pfade zum Kindprozess gibt, aber ich versuche, relative Pfade zu verwenden. Ich habe festgestellt, dass, wenn ich die Umgebungsvariable PYTHONPATH setze, dann kann ich importierte Module aus diesem Pfad ok und PYTHONPATH ist dort in sys.path , aber es scheint nicht, mit dem Verhalten von sys.path zu helfen. Ich habe auch versucht die Bearbeitung der sitecustomize.py Datei Hinzufügen PYTHONPATH zu os.environ , wie so

 # copy PYTHONPATH environment variable into PATH to allow our stuff to use # relative paths for subprocess spawning import os if os.getenv('PYTHONPATH') is not None and os.getenv('PATH') is not none: os.environ['PATH'] = ':'.join([os.getenv('PATH'), os.getenv('PYTHONPATH')]) 

Und überprüft, dass beim Start von Python, entweder interaktiv, mit ipython, oder indem Sie ein Skript aus der Kommandozeile, dass PYTHONPATH erfolgreich erscheint in os.environ . Allerdings subrocess.Popen immer noch nicht für die ausführbare Datei. Ich dachte, es sollte die Elternumgebung erben, wenn kein env kwarg angegeben ist? Als nächstes versuchte ich, env explizit zu geben, zuerst indem ich eine Kopie von os.getenv und zweitens nur indem os.getenv env={'PATH': '/explicit/path/to/search/from'} os.getenv und es immer noch nicht die ausführbare Datei findet . Jetzt bin ich stumped

Hoffentlich wird ein Beispiel dazu beitragen, mein Problem klarer zu erklären:

/ Dir / subdir1 / some_executable
/dir/subdir2/some_script.py

 # some_script.py from subprocess import Popen, PIPE spam, eggs = Popen(['../subdir1/some_executable'], stdout=PIPE, stderr=PIPE).communicate() 

Wenn ich in /dir/subdir2 und ich laufe python some_script.py es funktioniert, aber wenn ich bin in /dir und ich laufe python subdir2/some_script.py obwohl /dir/subdir2 ist in der os.environ['PATH'] , dann OSError: [Errno 2] No such file or directory werfen OSError: [Errno 2] No such file or directory .

  • So ändern Sie die Standard-Anaconda-Python-Umgebung
  • Eclipse-Umgebung für Maya-Python-Module
  • Skript läuft gut im Terminal aber nicht von launchd
  • Probleme mit Umlauten in python appdata environvent variabel
  • Was ist meine aktuelle Desktop-Umgebung?
  • Laufen Einheit Tests mit Nase in einer Python-Umgebung wie Autodesk Maya?
  • Python-Bereitstellung und / usr / bin / env-Portabilität
  • Wie bekomme ich virtualenv, um Dist-Pakete auf Ubuntu zu benutzen?
  • 4 Solutions collect form web for “Python subprocess Popen umgebung PATH?”

    (Ausfüllen von Details aus einem Kommentar, um eine separate Antwort zu machen)

    Zuerst werden die relativen Pfade (Pfade, die Schrägstriche enthalten) niemals in irgendeinem PATH eingecheckt, egal was du tust. Sie sind nur relativ zum aktuellen Arbeitsverzeichnis . Wenn du relative Pfade auflösen musst, musst du den PATH manuell durchsuchen oder den PATH abfangen, um die Unterverzeichnisse einzuschließen und dann einfach den Befehlsnamen wie in meinem Vorschlag unten zu verwenden.

    Wenn Sie ein Programm relativ zum Speicherort des Python-Skripts __file__ , verwenden Sie __file__ und gehen von dort aus, um den absoluten Pfad des Programms zu finden und dann den absoluten Pfad in Popen .

    Zweitens gibt es ein Problem in der Python-Bug-Tracker darüber, wie Python mit bloßen Befehlen (keine Schrägstriche) behandelt. Grundsätzlich auf Unix / Mac Popen verwendet os.execvp wenn mit shell=False aufgerufen, was bedeutet, dass es auf den Wert von PATH wie es war, wenn Python gestartet und keine Menge an ändernden os.environ wird Ihnen helfen, das zu beheben bedeutet. Auch bei Windows mit shell=False , gibt es keine Aufmerksamkeit auf PATH überhaupt, und wird nur in relativ zum aktuellen Arbeitsverzeichnis suchen.

    Wenn du gerade eine Path-Auswertung benötigst und deine Kommandozeile nicht wirklich durch eine Shell laufen möchtest und auf UNIX ist, empfehle ich mit env statt shell=True , wie bei Popen(['/usr/bin/env', 'progtorun', other, args], ...) . Damit können Sie einen anderen PATH an den env Prozess weitergeben, der es benutzt, um das Programm zu finden. Es vermeidet auch Probleme mit Shell-Metazeichen und potenziellen Sicherheitsfragen mit übergebenden Argumenten durch die Shell. Offensichtlich, auf Windows (so ziemlich die einzige Plattform ohne a /usr/bin/env ) müssen Sie etwas anderes machen.

    Sie scheinen ein wenig verwirrt über die Natur von PATH und PYTHONPATH .

    PATH ist eine Umgebungsvariable, die der OS-Shell mitteilt, wo sie nach ausführbaren Dateien suchen können.

    PYTHONPATH ist eine Umgebungsvariable, die dem Python-Interpreter angibt, wo man nach Modulen sucht, um zu importieren. Es hat nichts mit subprocess finding ausführbare Dateien zu tun.

    Aufgrund der Unterschiede in der zugrunde liegenden Implementierung wird subprocess.Popen nur den Pfad standardmäßig auf Nicht-Windows-Systemen durchsuchen (Windows hat einige Systemverzeichnisse, die es immer durchsucht, aber das unterscheidet sich von der PATH Verarbeitung). Die einzige zuverlässige plattformübergreifende Möglichkeit, den Pfad zu scannen, ist, indem man shell=True zum Subprocess-Call überträgt, aber das hat seine eigenen Themen (wie in der Popen Dokumentation beschrieben )

    Allerdings scheint es Ihr Hauptproblem ist, dass Sie ein Pfadfragment an Popen anstatt einen einfachen Dateinamen übergeben. Sobald Sie dort ein Verzeichnis separator haben, werden Sie die PATH Suche auch auf einer Nicht-Windows-Plattform deaktivieren (zB die Linux-Dokumentation für die ausführende Familie von Funktionen ).

    Ein relativer Pfad in subprocess.Popen wirkt relativ zum aktuellen Arbeitsverzeichnis, nicht die Elemente der Systeme PATH. Wenn Sie python subdir2/some_script.py aus /dir /dir/../subdir2/some_executable , als der erwartete ausführbare Standort wird /dir/../subdir2/some_executable , aka /subdir2/some_executable .

    Wenn Sie auf jeden Fall relative Pfade von einem eigenen Skripts-eigenen Verzeichnis zu einer bestimmten ausführbaren Datei verwenden möchten, wäre die beste Option, zuerst einen absoluten Pfad aus dem Verzeichnisbereich der globalen Variablen __file__ .

     #/usr/bin/env python from subprocess import Popen, PIPE from os.path import abspath, dirname, join path = abspath(join(dirname(__file__), '../subdir1/some_executable')) spam, eggs = Popen(path, stdout=PIPE, stderr=PIPE).communicate() 

    Der pythonpath ist auf den Pfad gesetzt, von wo aus der Python-Interpreter ausgeführt wird. Also, im zweiten Fall deines Beispiels ist der Pfad auf / dir und nicht / dir / subdir2 gesetzt. Deswegen bekommst du einen Fehler.

    Python ist die beste Programmiersprache der Welt.