Antworten:
Sie können verwenden __file__
, um den Namen der aktuellen Datei abzurufen. Bei Verwendung im Hauptmodul ist dies der Name des Skripts, das ursprünglich aufgerufen wurde.
Wenn Sie den Verzeichnisteil (der möglicherweise vorhanden ist) weglassen möchten, können Sie ihn verwenden os.path.basename(__file__)
.
__file__
ist im interaktiven Interpreter nicht definiert, da es dort bedeutungslos ist. Es wird von der Importimplementierung festgelegt. Wenn Sie also einen nicht standardmäßigen Importmechanismus verwenden, wird dieser möglicherweise auch nicht festgelegt.
import os
erforderlich ist, damit dies funktioniert. Ich würde dies in die Antwort aufnehmen.
import os
und import os.path
sind völlig gleichwertig.
import sys
print sys.argv[0]
Dies wird foo.py
für python foo.py
, dir/foo.py
für python dir/foo.py
usw. gedruckt . Es ist das erste Argument dafür python
. (Beachten Sie, dass es nach py2exe sein würde foo.exe
.)
python linkfile.py
, wo linkfile.py
ist ein Symlink zu realfile.py
, sys.argv[0]
wird 'linkfile.py'
, was kann oder kann nicht sein, was Sie wollen; es ist sicherlich das, was ich erwarte . __file__
ist das gleiche: es wird sein linkfile.py
. Wenn Sie wissen wollen , 'realfile.py'
aus 'linkfile.py'
, versuchen os.path.realpath('linkfile.py')
.
__file__
sondern stattdessen.
Der Vollständigkeit halber hielt ich es für sinnvoll, die verschiedenen möglichen Ergebnisse zusammenzufassen und Referenzen für das genaue Verhalten der einzelnen zu liefern:
__file__
ist die aktuell ausgeführte Datei, wie in der offiziellen Dokumentation beschrieben :
__file__
ist der Pfadname der Datei, aus der das Modul geladen wurde, wenn es aus einer Datei geladen wurde. Das__file__
Attribut fehlt möglicherweise für bestimmte Modultypen, z. B. C- Module, die statisch mit dem Interpreter verknüpft sind. Bei Erweiterungsmodulen, die dynamisch aus einer gemeinsam genutzten Bibliothek geladen werden, ist dies der Pfadname der gemeinsam genutzten Bibliotheksdatei.
Von Python3.4 ab, pro Ausgabe 18.416 , __file__
ist immer ein absoluter Pfad, es sei denn , die aktuell ausgeführte Datei ist ein Skript , das direkt (mit der nicht über den Interpreter ausgeführt wurde -m
unter Verwendung eines relativen Pfadbefehlszeilenoption).
__main__.__file__
(muss importiert werden __main__
) greift einfach auf das oben genannte __file__
Attribut des Hauptmoduls zu , z. B. des Skripts, das über die Befehlszeile aufgerufen wurde.
sys.argv[0]
(muss importiert werden sys
) ist der Skriptname, der über die Befehlszeile aufgerufen wurde und möglicherweise ein absoluter Pfad ist, wie in der offiziellen Dokumentation beschrieben :
argv[0]
ist der Skriptname (es hängt vom Betriebssystem ab, ob dies ein vollständiger Pfadname ist oder nicht). Wenn der Befehl mit der-c
Befehlszeilenoption für den Interpreter ausgeführt wurde,argv[0]
wird er auf die Zeichenfolge gesetzt'-c'
. Wenn kein Skriptname an den Python-Interpreter übergeben wurde,argv[0]
ist dies die leere Zeichenfolge.
Wie in einer anderen Antwort auf diese Frage erwähnt , zeigen Python- Skripte, die über Tools wie py2exe oder PyInstaller in eigenständige ausführbare Programme konvertiert wurden, bei Verwendung dieses Ansatzes möglicherweise nicht das gewünschte Ergebnis an (dh sys.argv[0]
sie enthalten eher den Namen der ausführbaren Datei als den Namen der Python- Hauptdatei in dieser ausführbaren Datei).
Wenn keine der oben genannten Optionen zu funktionieren scheint, wahrscheinlich aufgrund eines unregelmäßigen Importvorgangs, kann sich das Inspektionsmodul als nützlich erweisen. Insbesondere könnte das Aufrufen von inspect.getfile(...)
on inspect.currentframe()
funktionieren, obwohl letzteres zurückkehren würde ,None
wenn es in einer Implementierung ohne Python- Stack-Frame ausgeführt wird.
Wenn das aktuelle Skript eine symbolische Verknüpfung ist, geben alle oben genannten Elemente den Pfad der symbolischen Verknüpfung und nicht den Pfad der realen Datei zurück und os.path.realpath(...)
sollten aufgerufen werden, um letztere zu extrahieren.
os.path.basename(...)
kann auf einem der oben genannten Punkte aufgerufen werden, um den tatsächlichen Dateinamen zu extrahieren, und os.path.splitext(...)
kann auf dem tatsächlichen Dateinamen aufgerufen werden, um sein Suffix wie in abzuschneiden os.path.splitext(os.path.basename(...))
.
Ab Python 3.4 kann gemäß PEP 428 die PurePath
Klasse des pathlib
Moduls auch für alle oben genannten Zwecke verwendet werden. Insbesondere pathlib.PurePath(...).name
extrahiert die tatsächlichen Dateinamen und pathlib.PurePath(...).stem
extrahiert die tatsächlichen Dateinamen ohne seine Suffix.
Beachten Sie, __file__
dass die Datei, in der sich dieser Code befindet, importiert werden kann und sich von der zu interpretierenden Hauptdatei unterscheidet. Um die Hauptdatei zu erhalten, kann das spezielle Modul __main__ verwendet werden:
import __main__ as main
print(main.__file__)
Beachten Sie, dass dies __main__.__file__
in Python 2.7 funktioniert, jedoch nicht in 3.2. Verwenden Sie daher die oben beschriebene Import-as-Syntax, um es portabel zu machen.
rPython
Paket aus der R
Sprache verwende. Das muss ein Ausnahmefall sein, der einfach zu schwer zu handhaben ist.
__main__
intern importiert , um Variablen zwischen R
und zu übergeben python
. Daher wäre es relativ einfach, es __main__.__file__
vor dem Aufrufen von etwas anderem festzulegen, aber ich bin mir nicht einmal sicher, welcher Wert in diesem Fall angemessen wäre.
Die obigen Antworten sind gut. Aber ich fand diese Methode unter Verwendung der obigen Ergebnisse effizienter.
Dies führt dazu, dass der tatsächliche Name der Skriptdatei kein Pfad ist.
import sys
import os
file_name = os.path.basename(sys.argv[0])
Für moderne Python-Versionen (3.4+) Path(__file__).name
sollte idiomatischer sein. Außerdem Path(__file__).stem
haben Sie die Skriptnamen ohne die .py
Erweiterung.
from pathlib import Path
zuerst.
pathlib
wurde in Python 3.4 eingeführt, daher sollte es ab Python 3.4 funktionieren.
Angenommen, der Dateiname ist foo.py
das folgende Snippet
import sys
print sys.argv[0][:-3]
oder
import sys
print sys.argv[0][::-1][3:][::-1]
Wie bei anderen Erweiterungen mit mehr Zeichen, zum Beispiel dem Dateinamen foo.pypy
import sys
print sys.argv[0].split('.')[0]
Wenn Sie aus einem absoluten Pfad extrahieren möchten
import sys
print sys.argv[0].split('/')[-1].split('.')[0]
wird ausgegeben foo
__file__
und sys.argv[0]
, siehe stackoverflow.com/questions/5851588/…
Das erste Argument in sys ist der aktuelle Dateiname, damit dies funktioniert
import sys
print sys.argv[0] # will print the file name
Wenn Sie einen ungewöhnlichen Import durchführen (z. B. eine Optionsdatei), versuchen Sie Folgendes:
import inspect
print (inspect.getfile(inspect.currentframe()))
Beachten Sie, dass dadurch der absolute Pfad zur Datei zurückgegeben wird.
Wir können dies versuchen, um den aktuellen Skriptnamen ohne Erweiterung zu erhalten.
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
Alle diese Antworten sind großartig, haben aber einige Probleme, die Sie möglicherweise nicht auf den ersten Blick sehen.
Lassen Sie uns definieren, was wir wollen - wir wollen den Namen des Skripts, das ausgeführt wurde, nicht den Namen des aktuellen Moduls - also __file__
funktioniert es nur, wenn es im ausgeführten Skript verwendet wird, nicht in einem importierten Modul.
sys.argv
ist auch fraglich - was wäre, wenn Ihr Programm von pytest aufgerufen würde? oder Pydoc Runner? oder wenn es von uwsgi aufgerufen wurde?
und - es gibt eine dritte Methode, um den Skriptnamen zu erhalten, die ich in den Antworten nicht gesehen habe - Sie können den Stapel überprüfen.
Ein weiteres Problem ist, dass Sie (oder ein anderes Programm) mit sys.argv
und manipulieren können__main__.__file__
- es könnte vorhanden sein, es könnte nicht sein. Es könnte gültig sein oder nicht. Zumindest können Sie überprüfen, ob das Skript (das gewünschte Ergebnis) vorhanden ist!
Meine Bibliothek bitranox / lib_programname bei github macht genau das:
__main__
vorhanden__main__.__file__
vorhanden__main__.__file__
ein gültiges Ergebnis (existiert dieses Skript?)durch diese Art und Weise, meine Lösung funktioniert so weit mit setup.py test
, uwsgi
, pytest
, pycharm pytest
, pycharm docrunner (doctest)
, dreampie
,eclipse
Es gibt auch einen schönen Blog-Artikel über dieses Problem von Dough Hellman, "Bestimmen des Namens eines Prozesses aus Python".
os.path.abspath(__file__)
gibt Ihnen einen absoluten Pfad (auch relpath()
verfügbar).
sys.argv[-1]
gibt Ihnen einen relativen Pfad.
Ab Python 3.5 können Sie einfach Folgendes tun:
from pathlib import Path
Path(__file__).stem
Weitere Informationen finden Sie hier: https://docs.python.org/3.5/library/pathlib.html#pathlib.PurePath.stem
Zum Beispiel habe ich eine Datei unter meinem Benutzerverzeichnis mit dem folgenden Namen test.py
:
from pathlib import Path
print(Path(__file__).stem)
print(__file__)
Ausführen dieser Ausgänge:
>>> python3.6 test.py
test
test.py
Exception NameError: NameError("global name '__file__' is not defined",)
"