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 Anrufe script_2.py.
  • Im Gegenzug, script_2.py Anrufe script_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.)

War es hilfreich?

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)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top