1110 Stimmen

Wie kann der Pfad eines Moduls abgerufen werden?

Ich möchte feststellen, ob sich das Modul geändert hat. Die Verwendung von inotify ist einfach, Sie müssen nur das Verzeichnis kennen, von dem Sie Benachrichtigungen erhalten möchten.

Wie kann ich den Pfad eines Moduls in Python abrufen?

1300voto

orestis Punkte 14909
import a_module
print(a_module.__file__)

gibt Ihnen den Pfad zu der geladenen .pyc-Datei an, zumindest unter Mac OS X. Ich denke also, dass Sie das tun können:

import os
path = os.path.abspath(a_module.__file__)

Sie können auch versuchen:

path = os.path.dirname(a_module.__file__)

Um das Verzeichnis des Moduls zu erhalten.

385voto

Tomas Tomecek Punkte 5536

Es gibt inspect Modul in Python.

Offizielle Dokumentation

Das Modul inspect bietet mehrere nützliche Funktionen, um Informationen über Live-Objekte wie Module, Klassen, Methoden, Funktionen, Tracebacks, Frame-Objekte und Code-Objekte. Zum Beispiel, kann es Ihnen helfen, den Inhalt einer Klasse zu untersuchen, den Quellcode einer Methode abzurufen Quellcode einer Methode abrufen, die Argumentliste einer Funktion extrahieren und formatieren, oder Sie erhalten alle Informationen, die Sie zur Anzeige eines detaillierten Tracebacks benötigen.

Beispiel:

>>> import os
>>> import inspect
>>> inspect.getfile(os)
'/usr/lib64/python2.7/os.pyc'
>>> inspect.getfile(inspect)
'/usr/lib64/python2.7/inspect.pyc'
>>> os.path.dirname(inspect.getfile(inspect))
'/usr/lib64/python2.7'

82voto

mcstrother Punkte 5907

Wie bereits in den anderen Antworten erwähnt, ist es am besten, dies mit __file__ (unten noch einmal demonstriert). Es gibt jedoch einen wichtigen Vorbehalt, nämlich den, dass __file__ existiert NICHT, wenn Sie das Modul eigenständig ausführen (d. h. als __main__ ).

Nehmen wir zum Beispiel an, Sie haben zwei Dateien (die beide in Ihrem PYTHONPATH liegen):

#/path1/foo.py
import bar
print(bar.__file__)

y

#/path2/bar.py
import os
print(os.getcwd())
print(__file__)

Wenn Sie foo.py ausführen, erhalten Sie diese Ausgabe:

/path1        # "import bar" causes the line "print(os.getcwd())" to run
/path2/bar.py # then "print(__file__)" runs
/path2/bar.py # then the import statement finishes and "print(bar.__file__)" runs

JEDOCH, wenn Sie versuchen, bar.py allein auszuführen, erhalten Sie:

/path2                              # "print(os.getcwd())" still works fine
Traceback (most recent call last):  # but __file__ doesn't exist if bar.py is running as main
  File "/path2/bar.py", line 3, in <module>
    print(__file__)
NameError: name '__file__' is not defined 

Ich hoffe, das hilft. Diese Warnung kostete mich viel Zeit und Verwirrung beim Testen der anderen vorgestellten Lösungen.

75voto

jpgeek Punkte 4631

Ich werde versuchen, auch diese Frage in einigen Variationen zu behandeln:

  1. den Pfad des aufgerufenen Skripts finden
  2. den Pfad des aktuell ausgeführten Skripts finden
  3. das Verzeichnis des aufgerufenen Skripts finden

(Einige dieser Fragen wurden bereits auf SO gestellt, wurden aber als Duplikate geschlossen und hierher weitergeleitet).

Vorbehalte gegen die Verwendung __file__

Für ein Modul, das Sie importiert haben:

import something
something.__file__ 

gibt die absolut Pfad des Moduls. Bei folgendem Skript foo.py:

#foo.py
print '__file__', __file__

Ein Aufruf mit 'python foo.py' gibt einfach 'foo.py' zurück. Wenn Sie einen Shebang hinzufügen:

#!/usr/bin/python 
#foo.py
print '__file__', __file__

und rufen Sie es mit ./foo.py auf, wird es './foo.py' zurückgeben. Ruft man es aus einem anderen Verzeichnis auf (z.B. foo.py im Verzeichnis bar), dann ruft man entweder

python bar/foo.py

oder einen Shebang hinzufügen und die Datei direkt ausführen:

bar/foo.py

wird 'bar/foo.py' zurückgeben (die relativ Pfad).

Suche nach dem Verzeichnis

Von dort aus können Sie nun das Verzeichnis abrufen, os.path.dirname(__file__) kann auch knifflig sein. Zumindest auf meinem System gibt es eine leere Zeichenfolge zurück, wenn Sie es aus dem gleichen Verzeichnis wie die Datei aufrufen.

# foo.py
import os
print '__file__ is:', __file__
print 'os.path.dirname(__file__) is:', os.path.dirname(__file__)

wird ausgegeben:

__file__ is: foo.py
os.path.dirname(__file__) is: 

Mit anderen Worten, es wird eine leere Zeichenkette zurückgegeben, so dass dies nicht zuverlässig erscheint, wenn Sie es für die aktuelle Datei (im Gegensatz zu den Datei eines importierten Moduls). Um dies zu umgehen, können Sie es in einen Aufruf von abspath verpacken:

# foo.py
import os
print 'os.path.abspath(__file__) is:', os.path.abspath(__file__)
print 'os.path.dirname(os.path.abspath(__file__)) is:', os.path.dirname(os.path.abspath(__file__))

die etwas wie ausgibt:

os.path.abspath(__file__) is: /home/user/bar/foo.py
os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar

Beachten Sie, dass abspath() Symlinks NICHT auflöst. Wenn Sie dies tun wollen, verwenden Sie stattdessen realpath(). Beispiel: Erstellen Sie einen Symlink file_import_testing_link, der auf file_import_testing.py zeigt, mit dem folgenden Inhalt:

import os
print 'abspath(__file__)',os.path.abspath(__file__)
print 'realpath(__file__)',os.path.realpath(__file__)

ausführt, werden absolute Pfade etwa so ausgegeben:

abspath(__file__) /home/user/file_test_link
realpath(__file__) /home/user/file_test.py

file_import_testing_link -> file_import_testing.py

Mit inspect

@SummerBreeze erwähnt die Verwendung des prüfen Modul.

Dies scheint gut zu funktionieren und ist bei importierten Modulen recht übersichtlich:

import os
import inspect
print 'inspect.getfile(os) is:', inspect.getfile(os)

gibt gehorsamst den absoluten Pfad zurück. Zum Auffinden des Pfads des aktuell ausgeführten Skripts:

inspect.getfile(inspect.currentframe())

(danke @jbochi)

inspect.getabsfile(inspect.currentframe()) 

gibt den absoluten Pfad des aktuell ausgeführten Skripts an (danke @Sadman_Sakib).

52voto

PlasmaBinturong Punkte 1728

Ich verstehe nicht, warum niemand darüber spricht, aber für mich ist die einfachste Lösung die Verwendung von imp.find_module("modulname") (Dokumentation aquí ) :

import imp
imp.find_module("os")

Es ergibt ein Tupel mit dem Pfad an zweiter Stelle:

(<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>,
'/usr/lib/python2.7/os.py',
('.py', 'U', 1))

Der Vorteil dieser Methode gegenüber der "inspect"-Methode ist, dass man das Modul nicht importieren muss, damit sie funktioniert, und dass man einen String als Eingabe verwenden kann. Nützlich z.B. bei der Überprüfung von Modulen, die in einem anderen Skript aufgerufen werden.

EDIT :

In python3, importlib Modul tun sollte:

Dokument von importlib.util.find_spec :

Gibt die Spezifikation für das angegebene Modul zurück.

Zunächst wird in sys.modules geprüft, ob das Modul bereits importiert wurde. Wenn ja, dann wird sys.modules[name]. spec zurückgegeben wird. Wenn dieser zufällig auf auf None gesetzt, dann wird ValueError ausgelöst. Wenn sich das Modul nicht in sys.modules, dann wird sys.meta_path nach einer geeigneten Spezifikation mit dem Wert von 'path' an die Finder übergeben. Keine wird zurückgegeben, wenn keine Spezifikation gefunden wird.

Wenn der Name für ein Submodul steht (einen Punkt enthält), ist das übergeordnete Modul automatisch importiert.

Die Argumente name und package funktionieren genauso wie importlib.import_module(). Mit anderen Worten: relative Modulnamen (mit führenden Punkten) funktionieren.

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