364 Stimmen

Wie bestimmen Sie das aktuelle Skriptverzeichnis richtig?

Ich möchte sehen, was ist der beste Weg, um das aktuelle Skript-Verzeichnis in Python zu bestimmen.

Ich habe festgestellt, dass es aufgrund der vielen Möglichkeiten, Python-Code aufzurufen, schwierig ist, eine gute Lösung zu finden.

Hier sind einige Probleme:

  • __file__ ist nicht definiert, wenn das Skript mit exec , execfile
  • __module__ ist nur in Modulen definiert

Anwendungsfälle:

  • ./myfile.py
  • python myfile.py
  • ./somedir/myfile.py
  • python somedir/myfile.py
  • execfile('myfile.py') (von einem anderen Skript, das sich in einem anderen Verzeichnis befinden kann und ein anderes aktuelles Verzeichnis haben kann.

Ich weiß, dass es keine perfekte Lösung gibt, aber ich bin auf der Suche nach dem besten Ansatz, der die meisten Fälle löst.

Der am häufigsten verwendete Ansatz ist os.path.dirname(os.path.abspath(__file__)) aber das funktioniert nicht, wenn Sie das Skript von einem anderen Skript aus ausführen mit exec() .

Warnung

Jede Lösung, die das aktuelle Verzeichnis verwendet, wird fehlschlagen. Dieses kann je nach Art des Skriptaufrufs unterschiedlich sein oder innerhalb des laufenden Skripts geändert werden.

299voto

bobince Punkte 512550
os.path.dirname(os.path.abspath(__file__))

ist in der Tat das Beste, was Sie bekommen werden.

Es ist ungewöhnlich, ein Skript auszuführen mit exec / execfile Normalerweise sollten Sie die Modulinfrastruktur zum Laden von Skripten verwenden. Wenn Sie diese Methoden verwenden müssen, schlage ich vor, dass Sie __file__ im globals die Sie dem Skript übergeben, damit es diesen Dateinamen lesen kann.

Es gibt keine andere Möglichkeit, den Dateinamen im ausgeführten Code zu erhalten: Wie Sie bemerken, kann sich der CWD an einer völlig anderen Stelle befinden.

148voto

Sven Marnach Punkte 525472

Wenn Sie wirklich den Fall abdecken wollen, dass ein Skript über execfile(...) können Sie die inspect Modul, um den Dateinamen (einschließlich des Pfads) zu ermitteln. Soweit ich weiß, funktioniert dies in allen von Ihnen genannten Fällen:

filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))

51voto

Eugene Yarmash Punkte 130008

In Python 3.4+ können Sie die einfachere pathlib Modul:

from inspect import currentframe, getframeinfo
from pathlib import Path

filename = getframeinfo(currentframe()).filename
parent = Path(filename).resolve().parent

Sie können auch Folgendes verwenden __file__ (wenn sie verfügbar ist), um die inspect Modul in seiner Gesamtheit:

from pathlib import Path
parent = Path(__file__).resolve().parent

50voto

jfs Punkte 370717
#!/usr/bin/env python
import inspect
import os
import sys

def get_script_dir(follow_symlinks=True):
    if getattr(sys, 'frozen', False): # py2exe, PyInstaller, cx_Freeze
        path = os.path.abspath(sys.executable)
    else:
        path = inspect.getabsfile(get_script_dir)
    if follow_symlinks:
        path = os.path.realpath(path)
    return os.path.dirname(path)

print(get_script_dir())

Es funktioniert mit CPython, Jython und Pypy. Es funktioniert, wenn das Skript ausgeführt wird mit execfile() ( sys.argv[0] y __file__ -basierten Lösungen würden hier versagen). Es funktioniert, wenn sich das Skript innerhalb von eine ausführbare Zip-Datei (/an egg) . Es funktioniert, wenn das Skript "importiert" wird ( PYTHONPATH=/path/to/library.zip python -mscript_to_run ) aus einer Zip-Datei; es gibt in diesem Fall den Archivpfad zurück. Es funktioniert, wenn das Skript zu einer eigenständigen ausführbaren Datei kompiliert wird ( sys.frozen ). Es funktioniert für Symlinks ( realpath beseitigt symbolische Links). Es funktioniert in einem interaktiven Interpreter; in diesem Fall gibt es das aktuelle Arbeitsverzeichnis zurück.

37voto

Ron Kalian Punkte 2614

En os.path... Ansatz war in Python 2 "in Mode".

In Python 3 finden Sie das Verzeichnis des Skripts wie folgt:

from pathlib import Path
script_path = Path(__file__).parent

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X