Wie erhalte ich den Pfad und Namen der Datei, die gerade ausgeführt wird?
Frage
Ich habe Skripte, die andere Skriptdateien aufrufen, aber ich muss den Dateipfad der Datei abrufen, die derzeit im Prozess ausgeführt wird.
Nehmen wir zum Beispiel an, ich habe drei Dateien.Benutzen Exec-Datei:
script_1.py
Anrufescript_2.py
.- Im Gegenzug,
script_2.py
Anrufescript_3.py
.
Wie kann ich den Dateinamen und den Pfad von erhalten? script_3.py
, aus dem Code im Inneren script_3.py
, ohne diese Informationen als Argumente von übergeben zu müssen script_2.py
?
(Ausführen os.getcwd()
gibt den Dateipfad des ursprünglichen Startskripts zurück, nicht den der aktuellen Datei.)
Lösung
p1.py:
execfile("p2.py")
p2.py:
import inspect, os
print inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory
Andere Tipps
__file__
wie andere schon gesagt haben.Möglicherweise möchten Sie auch verwenden os.path.realpath So entfernen Sie Symlinks:
import os
os.path.realpath(__file__)
Update 28.11.2018:
Hier ist eine Zusammenfassung der Experimente mit Python 2 und 3.Mit
main.py – führt foo.py aus
foo.py – führt lib/bar.py aus
lib/bar.py – druckt Dateipfadausdrücke
| Python | Run statement | Filepath expression |
|--------+---------------------+----------------------------------------|
| 2 | execfile | os.path.abspath(inspect.stack()[0][1]) |
| 2 | from lib import bar | __file__ |
| 3 | exec | (wasn't able to obtain it) |
| 3 | import lib.bar | __file__ |
Für Python 2 ist es möglicherweise klarer, auf Pakete umzusteigen, die Sie verwenden können from lib import bar
- einfach leer hinzufügen __init__.py
Dateien in die beiden Ordner.
Für Python 3, execfile
existiert nicht - die nächstgelegene Alternative ist exec(open(<filename>).read())
, obwohl dies Auswirkungen auf die Stapelrahmen hat.Es ist am einfachsten, es einfach zu verwenden import foo
Und import lib.bar
- NEIN __init__.py
Dateien benötigt.
Siehe auch Unterschied zwischen Import- und Exec-Datei
Ursprüngliche Antwort:
Hier ist ein Experiment basierend auf den Antworten in diesem Thread – mit Python 2.7.10 unter Windows.
Die stapelbasierten Methoden scheinen die einzigen zu sein, die zuverlässige Ergebnisse liefern.Die letzten beiden haben die kürzeste Syntax, d.h.-
print os.path.abspath(inspect.stack()[0][1]) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib
Hier erfahren Sie, wie diese ergänzt werden sys als Funktionen!Dank an @Usagi und @pablog
Basierend auf den folgenden drei Dateien und dem Ausführen von main.py aus seinem Ordner mit python main.py
(habe es auch mit Exec-Dateien mit absoluten Pfaden und dem Aufruf aus einem separaten Ordner versucht).
C:\filepaths\main.py: execfile('foo.py')
C:\filepaths\foo.py: execfile('lib/bar.py')
C:\filepaths\lib\bar.py:
import sys
import os
import inspect
print "Python " + sys.version
print
print __file__ # main.py
print sys.argv[0] # main.py
print inspect.stack()[0][1] # lib/bar.py
print sys.path[0] # C:\filepaths
print
print os.path.realpath(__file__) # C:\filepaths\main.py
print os.path.abspath(__file__) # C:\filepaths\main.py
print os.path.basename(__file__) # main.py
print os.path.basename(os.path.realpath(sys.argv[0])) # main.py
print
print sys.path[0] # C:\filepaths
print os.path.abspath(os.path.split(sys.argv[0])[0]) # C:\filepaths
print os.path.dirname(os.path.abspath(__file__)) # C:\filepaths
print os.path.dirname(os.path.realpath(sys.argv[0])) # C:\filepaths
print os.path.dirname(__file__) # (empty string)
print
print inspect.getfile(inspect.currentframe()) # lib/bar.py
print os.path.abspath(inspect.getfile(inspect.currentframe())) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:\filepaths\lib
print
print os.path.abspath(inspect.stack()[0][1]) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib
print
Ich denke, das ist sauberer:
import inspect
print inspect.stack()[0][1]
und erhält die gleichen Informationen wie:
print inspect.getfile(inspect.currentframe())
Dabei ist [0] der aktuelle Frame im Stapel (oben im Stapel) und [1] der Dateiname. Erhöhen Sie die Zahl, um im Stapel rückwärts zu gehen, d. h.
print inspect.stack()[1][1]
wäre der Dateiname des Skripts, das den aktuellen Frame aufgerufen hat.Wenn Sie [-1] verwenden, gelangen Sie außerdem zum Ende des Stapels, dem ursprünglichen aufrufenden Skript.
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
Die als am besten markierten Vorschläge treffen alle zu, wenn Ihr Skript nur aus einer Datei besteht.
Wenn Sie den Namen der ausführbaren Datei herausfinden möchten (d. h.die Root-Datei, die an den Python-Interpreter für das aktuelle Programm übergeben wird) aus einer Datei, die als Modul importiert werden kann, müssen Sie dies tun (nehmen wir an, dass es sich um eine Datei mit dem Namen handelt). foo.py):
import inspect
print inspect.stack()[-1][1]
Weil das Letzte ([-1]
) auf dem Stapel ist das erste, was darin enthalten ist (Stacks sind LIFO/FILO-Datenstrukturen).
Dann in der Akte bar.py wenn du import foo
es wird gedruckt bar.py, statt foo.py, was der Wert von all diesen wäre:
__file__
inspect.getfile(inspect.currentframe())
inspect.stack()[0][1]
import os
print os.path.basename(__file__)
Dadurch erhalten wir nur den Dateinamen.d.h.Wenn der Abspfad der Datei c:\abcd\abc.py ist, wird in der zweiten Zeile abc.py gedruckt
Es ist nicht ganz klar, was Sie unter „dem Dateipfad der Datei, die gerade im Prozess ausgeführt wird“ verstehen.sys.argv[0]
Enthält normalerweise den Speicherort des Skripts, das vom Python-Interpreter aufgerufen wurde.Überprüf den sys-Dokumentation für mehr Details.
Wie @Tim und @Pat Notz betont haben, bietet das Attribut __file__ Zugriff auf
Die Datei, aus der das Modul geladen wurde, wenn es aus einer Datei geladen wurde
Ich habe ein Skript, das unter einer Windows-Umgebung funktionieren muss.Mit diesem Codeausschnitt habe ich fertig:
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
Es ist eine ziemlich schwierige Entscheidung.Aber es erfordert keine externen Bibliotheken und ist in meinem Fall das Wichtigste.
import os
os.path.dirname(os.path.abspath(__file__))
Keine Notwendigkeit für Inspect oder eine andere Bibliothek.
Dies funktionierte bei mir, als ich ein Skript (aus einem anderen Verzeichnis als das ausgeführte Skript) importieren musste, das eine Konfigurationsdatei verwendete, die sich im selben Ordner wie das importierte Skript befand.
Der __file__
Das Attribut funktioniert sowohl für die Datei, die den Hauptausführungscode enthält, als auch für importierte Module.
Sehen https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
import sys
print sys.path[0]
Dies würde den Pfad des aktuell ausgeführten Skripts ausgeben
Ich denke, es ist gerecht __file__
Klingt so, als ob Sie sich das vielleicht auch ansehen möchten Modul prüfen.
Sie können verwenden inspect.stack()
import inspect,os
inspect.stack()[0] => (<frame object at 0x00AC2AC0>, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]\n'], 0)
os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py'
Versuche dies,
import os
os.path.dirname(os.path.realpath(__file__))
import sys
print sys.argv[0]
Das sollte funktionieren:
import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
Um das Verzeichnis des ausgeführten Skripts abzurufen
print os.path.dirname( inspect.getfile(inspect.currentframe()))
Um die Migrationskonsistenz auf allen Plattformen (macOS/Windows/Linux) aufrechtzuerhalten, versuchen Sie Folgendes:
path = r'%s' % os.getcwd().replace('\\','/')
print(__file__)
print(__import__("pathlib").Path(__file__).parent)
Ich habe den Ansatz mit __file__ verwendet
os.path.abspath(__file__)
Es gibt jedoch einen kleinen Trick, es gibt die .py -Datei zurück, wenn der Code zum ersten Mal ausgeführt wird. Als nächst
also blieb ich bei:
inspect.getfile(inspect.currentframe())
oder
sys._getframe().f_code.co_filename
Ich habe eine Funktion geschrieben, die Eclipse berücksichtigt Debugger Und Gerätetest.Es gibt den Ordner des ersten Skripts zurück, das Sie starten.Sie können optional die angeben __Datei__ var, aber die Hauptsache ist, dass Sie diese Variable nicht in allen Ihren teilen müssen Aufrufhierarchie.
Vielleicht können Sie damit umgehen, dass andere bestimmte Fälle stapeln, die ich nicht gesehen habe, aber für mich ist es in Ordnung.
import inspect, os
def getRootDirectory(_file_=None):
"""
Get the directory of the root execution file
Can help: http://stackoverflow.com/questions/50499/how-do-i-get-the-path-and-name-of-the-file-that-is-currently-executing
For eclipse user with unittest or debugger, the function search for the correct folder in the stack
You can pass __file__ (with 4 underscores) if you want the caller directory
"""
# If we don't have the __file__ :
if _file_ is None:
# We get the last :
rootFile = inspect.stack()[-1][1]
folder = os.path.abspath(rootFile)
# If we use unittest :
if ("/pysrc" in folder) & ("org.python.pydev" in folder):
previous = None
# We search from left to right the case.py :
for el in inspect.stack():
currentFile = os.path.abspath(el[1])
if ("unittest/case.py" in currentFile) | ("org.python.pydev" in currentFile):
break
previous = currentFile
folder = previous
# We return the folder :
return os.path.dirname(folder)
else:
# We return the folder according to specified __file__ :
return os.path.dirname(os.path.realpath(_file_))
Der einfachste Weg ist:
In script_1.py:
import subprocess
subprocess.call(['python3',<path_to_script_2.py>])
In script_2.py:
sys.argv[0]
P.S.:ich habe es versucht execfile
, aber da es script_2.py als String liest, sys.argv[0]
ist zurückgekommen <string>
.
Ich habe immer nur die Betriebssystemfunktion des aktuellen Arbeitsverzeichnisses (CWD) verwendet.Dies ist Teil der Standardbibliothek und sehr einfach zu implementieren.Hier ist ein Beispiel:
import os
base_directory = os.getcwd()
Die meisten dieser Antworten wurden in Python Version 2.x oder früher geschrieben.In Python 3.x hat sich die Syntax für die Druckfunktion geändert und erfordert nun Klammern, d. h.drucken().
Also, diese frühere Highscore-Antwort von user13993 in Python 2.x:
import inspect, os
print inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory
Wird in Python 3.x:
import inspect, os
print(inspect.getfile(inspect.currentframe())) # script filename (usually with path)
print(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) ) # script directory
wenn Sie nur den Dateinamen ohne möchten ./
oder .py
Sie können dies versuchen
filename = testscript.py
file_name = __file__[2:-3]
file_name
Drucken Sie Testscript Sie können alles generieren, was Sie wollen, indem Sie den Index in [] ändern [
import os
import wx
# return the full path of this file
print(os.getcwd())
icon = wx.Icon(os.getcwd() + '/img/image.png', wx.BITMAP_TYPE_PNG, 16, 16)
# put the icon on the frame
self.SetIcon(icon)