Wie eines Moduls Pfad abzurufen?
Frage
Ich möchte feststellen, ob Modul geändert hat. Nun kann mit inotify einfach ist, müssen Sie nur das Verzeichnis, das Sie von erhalten Benachrichtigungen wissen wollen.
Wie rufe ich einen Pfad des Moduls in Python?
Lösung
import a_module
print(a_module.__file__)
Wollen Sie tatsächlich geben Sie den Pfad zur .pyc-Datei, die geladen wurde, zumindest unter Mac OS X. Also ich denke, Sie tun können:
import os
path = os.path.dirname(a_module.__file__)
Sie können auch versuchen:
path = os.path.abspath(a_module.__file__)
Um die Modul Verzeichnis.
Andere Tipps
Es ist inspect
Modul in Python.
Offizielle Dokumentation
Das inspizieren Modul bietet mehrere nützliche Funktionen zu helfen Informationen über Live-Objekte wie Module, Klassen, Methoden, Funktionen, Tracebacks, Frame-Objekte und Codeobjekte. Zum Beispiel, es können Sie den Inhalt einer Klasse untersuchen helfen, rufen Sie die Quelle Code eines Verfahrens, extrahieren und formatieren die Argumentliste für eine Funktion, oder erhalten alle Informationen, die Sie eine detaillierte Rückverfolgung angezeigt werden müssen.
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'
Wie die anderen Antworten gesagt haben, ist der beste Weg, dies zu tun, ist mit __file__
(wieder unten gezeigt). Allerdings gibt es eine wichtige Einschränkung, die ist, dass __file__
nicht vorhanden ist, wenn Sie das Modul laufen auf seinem eigenen (das heißt als __main__
).
Zum Beispiel, sagen, Sie haben zwei Dateien (beide auf Ihrem PYTHONPATH sind):
#/path1/foo.py
import bar
print(bar.__file__)
und
#/path2/bar.py
import os
print(os.getcwd())
print(__file__)
foo.py Lauf gibt die 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
Wenn Sie jedoch auf eigene laufen bar.py versuchen, 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
Hoffe, das hilft. Diese Einschränkung kostete mich viel Zeit und Verwirrung, während die anderen vorgestellten Lösungen zu testen.
Ich werde versuchen, auch ein paar Variationen zu dieser Frage anzugehen:
- den Pfad des gerufenen Skript zu finden
- den Pfad des aktuell ausgeführten Skripts zu finden
- das Verzeichnis des aufgerufenen Skript zu finden
(Einige dieser Fragen auf SO gestellt wurden, haben aber als Duplikate und umgeleitet hier geschlossen.)
Caveats der Verwendung __file__
Für ein Modul, das Sie importiert haben:
import something
something.__file__
kehren den absoluten Pfad des Moduls. Um jedoch das Folowing Skript foo.py gegeben:
#foo.py
print '__file__', __file__
es Aufruf mit 'Python foo.py' einfach 'foo.py' zurückzukehren. Wenn Sie eine shebang hinzufügen:
#!/usr/bin/python
#foo.py
print '__file__', __file__
und rufen Sie es mit ./foo.py, wird es zurückgeben ‚./foo.py‘. Der Aufruf aus einem anderen Verzeichnis (zB setzen foo.py im Verzeichnis bar), dann ruft entweder
python bar/foo.py
oder eine shebang Hinzufügen und Ausführen der Datei direkt:
bar/foo.py
kehrt 'Bar / foo.py' (die relativ Pfad).
Finding das Verzeichnis
Jetzt geht von dort aus dem Verzeichnis zu erhalten, os.path.dirname(__file__)
kann auch schwierig sein. Zumindest auf meinem System, gibt es eine leere Zeichenfolge, wenn Sie es aus dem gleichen Verzeichnis wie die Datei aufrufen. ex.
# foo.py
import os
print '__file__ is:', __file__
print 'os.path.dirname(__file__) is:', os.path.dirname(__file__)
AUSGABE:
__file__ is: foo.py
os.path.dirname(__file__) is:
Mit anderen Worten, es gibt eine leere Zeichenfolge, so scheint dies nicht zuverlässig, wenn Sie es für die aktuelle Datei verwenden mögen (im Gegensatz zu der Datei von ein importiertes Modul). Um dies zu umgehen, können Sie es in einem Aufruf wickeln abspath:
# 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__))
, welche Ausgänge so etwas wie:
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 lösen. Wenn Sie dies tun wollen, verwenden Sie realpath () statt. Zum Beispiel macht einen Symlink file_import_testing_link file_import_testing.py zeigen, mit folgendem Inhalt:
import os
print 'abspath(__file__)',os.path.abspath(__file__)
print 'realpath(__file__)',os.path.realpath(__file__)
Ausführen wird absolute Pfade etwas drucken wie:
abspath(__file__) /home/user/file_test_link
realpath(__file__) /home/user/file_test.py
file_import_testing_link -> file_import_testing.py
Mit inspizieren
@SummerBreeze erwähnt die Modul href="http://docs.python.org/2/library/inspect.html"> überprüfen.
Das scheint gut zu funktionieren, und ist sehr prägnant, für importierte Module:
import os
import inspect
print 'inspect.getfile(os) is:', inspect.getfile(os)
folgsam gibt den absoluten Pfad. Doch für den Pfad des aktuell ausgeführten Skripts zu finden, ich habe keine Möglichkeit, es zu benutzen.
Ich erhalte nicht, warum niemand darüber spricht, aber für mich die einfachste Lösung ist mit imp.find_module ( "Modulname") (Dokumentation here ):
import imp
imp.find_module("os")
Es gibt ein Tupel mit dem Pfad in der zweiten Position:
(<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>,
'/usr/lib/python2.7/os.py',
('.py', 'U', 1))
Der Vorteil dieses Verfahrens gegenüber dem „inspizieren“ ist, dass Sie es nicht das Modul importieren müssen, um sicherzustellen zu arbeiten, und Sie können eine Zeichenfolge in Eingabe verwenden. Nützlich, wenn man beispielsweise genannt Module in einem anderen Skript zu überprüfen.
Bearbeiten :
In python3, importlib
Modul sollte tun:
Doc von importlib.util.find_spec
:
Gibt die Spezifikation für das angegebene Modul.
Als erstes wird sys.modules geprüft, ob das Modul bereits importiert wurde. Wenn ja, dann sys.modules [name]. spec zurückgegeben. Wenn das passiert zu sein auf None, wird dann angehoben Valueerror. Wenn das Modul nicht in sys.modules, dann wird sys.meta_path nach einem geeigneten spec gesucht mit der Wert von ‚Pfad‘ zu den Findern gegeben. Kein zurückgegeben, wenn kein spec konnte gefunden werden.
Wenn der Name für Submodul ist (enthält einen Punkt), die Mutter Modul automatisch importiert.
Die Namen und Paket Argumente funktionieren gleich wie importlib.import_module (). Mit anderen Worten, relativ Modulnamen (mit führenden Punkten) zu arbeiten.
Dies war trivial.
Jedes Modul hat eine __file__
Variable, die ihren relativen Pfad zeigt, von wo Sie gerade sind.
Daher ein Verzeichnis für das Modul immer zu benachrichtigen, es einfach ist, wie:
os.path.dirname(__file__)
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
Befehlszeilenprogramm
Sie können es zwicken auf ein Befehlszeilenprogramm,
python-which <package name>
Erstellen /usr/local/bin/python-which
#!/usr/bin/env python
import importlib
import os
import sys
args = sys.argv[1:]
if len(args) > 0:
module = importlib.import_module(args[0])
print os.path.dirname(module.__file__)
Machen Sie es ausführbar
sudo chmod +x /usr/local/bin/python-which
So verbrachte ich eine Menge Zeit versuchen, dies zu tun mit py2exe Das Problem war, den Basisordner des Skripts zu bekommen, ob es als ein Python-Skript oder als py2exe ausführbare Datei ausgeführt wurde. Auch sie arbeiten zu lassen, ob sie aus dem aktuellen Ordner ausgeführt wurde, einen anderen Ordner oder (dies war der schwierigste) aus dem Systempfad.
Schließlich habe ich diesen Ansatz, indem sys.frozen als Indikatoren in py2exe laufen:
import os,sys
if hasattr(sys,'frozen'): # only when running in py2exe this exists
base = sys.prefix
else: # otherwise this is a regular python script
base = os.path.dirname(os.path.realpath(__file__))
import module
print module.__path__
Pakete unterstützen ein weiteres spezielles Attribut,
__path__
. Das ist initialisierte eine Liste zu sein, den Namen des Verzeichnisses Halte enthalten das__init__.py
Paket vor dem Code in der Datei ausgeführt wird. Diese Variable kann verändert werden; dabei wirkt so Zukunft sucht Module und Subpackages in dem Paket enthalten ist.Während diese Funktion nicht oft benötigt wird, kann es verwendet werden die verlängern Set von Modulen in einem Paket gefunden.
Sie können einfach importieren Sie Ihre Modul dann traf seinen Namen und Sie den vollständigen Pfad
erhalten>>> import os
>>> os
<module 'os' from 'C:\\Users\\Hassan Ashraf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\os.py'>
>>>
Wenn die einzige Einschränkung __file__
der Verwendung ist, wenn der Strom relativ Verzeichnis leer ist (dh, wenn es als ein Skript aus dem gleichen Verzeichnis ausgeführt wird, wo das Skript ist), dann wird eine triviale Lösung ist:
import os.path
mydir = os.path.dirname(__file__) or '.'
full = os.path.abspath(mydir)
print __file__, mydir, full
Und das Ergebnis:
$ python teste.py
teste.py . /home/user/work/teste
Der Trick ist, in or '.'
nach dem dirname()
Anruf. Er setzt die dir als .
, was bedeutet, aktuelles Verzeichnis und ist ein gültiges Verzeichnis für jeden Weg verbundene Funktion.
So verwenden abspath()
ist nicht wirklich notwendig. Aber wenn Sie es trotzdem verwenden, wird der Trick nicht erforderlich. abspath()
leere Pfade akzeptiert und richtig interpretiert sie als das aktuelle Verzeichnis
Ich mag mit einem gemeinsamen Szenario (in Python 3) tragen und ein paar Ansätze, um es erkunden.
Die integrierte Funktion open () akzeptiert entweder relativ oder absoluter Pfad als erstes Argument. Der relative Pfad wird behandelt, als relativ zum aktuellen Arbeitsverzeichnis aber so ist es empfehlenswert, den absoluten Pfad zur Datei zu übergeben.
Einfach gesagt, wenn Sie eine Skript-Datei mit dem folgenden Code ausführen, es ist nicht garantiert, dass die example.txt
Datei wird im selben Verzeichnis erstellt, in dem die Skriptdatei befindet:
with open('example.txt', 'w'):
pass
Um diesen Code zu beheben wir den Pfad zum Skript erhalten müssen und es absolut zu machen. Um den Pfad zu gewährleisten zu sein, absolut wir einfach nutzen das os .path.realpath () Funktion. Um den Pfad zum Skript zu erhalten gibt es mehrere gemeinsame Funktionen, die verschiedenen Pfad Ergebnisse zurück:
-
os.getcwd()
-
os.path.realpath('example.txt')
-
sys.argv[0]
-
__file__
Beide Funktionen os.getcwd () und < a href = "https://docs.python.org/3/library/os.path.html#os.path.realpath" rel = "nofollow noreferrer"> os.path.realpath () Pfad zurückzukehren basierend Ergebnisse auf dem aktuellen Arbeitsverzeichnis . Im Allgemeinen nicht, was wir wollen. Das erste Element der sys.argv Liste ist die < em> Pfad des root-Skript (das Skript Sie ausführen), unabhängig davon, ob Sie die Liste im Stamm Skript aufrufen selbst oder in einem seiner Module. Es könnte in einigen Situationen als nützlich. Die __FILE__ Variable enthält Pfad des Moduls, von dem sie aufgerufen wurde .
Der folgende Code erstellt eine Datei korrekt example.txt
im gleichen Verzeichnis, in dem sich das Skript befindet:
filedir = os.path.dirname(os.path.realpath(__file__))
filepath = os.path.join(filedir, 'example.txt')
with open(filepath, 'w'):
pass
Von innerhalb von Modulen eines Python-Paket musste ich eine Datei verweisen, die in demselben Verzeichnis wie Paket residierten. Bsp.
some_dir/
maincli.py
top_package/
__init__.py
level_one_a/
__init__.py
my_lib_a.py
level_two/
__init__.py
hello_world.py
level_one_b/
__init__.py
my_lib_b.py
So oben Ich hatte maincli.py von my_lib_a.py Modul so nennen top_package und maincli.py sind im gleichen Verzeichnis zu kennen. Hier ist, wie ich den Weg bekommen maincli.py:
import sys
import os
import imp
class ConfigurationException(Exception):
pass
# inside of my_lib_a.py
def get_maincli_path():
maincli_path = os.path.abspath(imp.find_module('maincli')[1])
# top_package = __package__.split('.')[0]
# mod = sys.modules.get(top_package)
# modfile = mod.__file__
# pkg_in_dir = os.path.dirname(os.path.dirname(os.path.abspath(modfile)))
# maincli_path = os.path.join(pkg_in_dir, 'maincli.py')
if not os.path.exists(maincli_path):
err_msg = 'This script expects that "maincli.py" be installed to the '\
'same directory: "{0}"'.format(maincli_path)
raise ConfigurationException(err_msg)
return maincli_path
Basierend auf der Veröffentlichung von PlasmaBinturong modifizierte ich den Code.
Wenn Sie dies in einem „Programm“ dynamisch zu tun versuchen, diesen Code:
Mein Punkt ist, können Sie nicht den genauen Namen des Moduls kennen können „hart codiert“ es.
Es kann aus einer Liste ausgewählt werden oder derzeit nicht ausgeführt werden kann, __file verwenden __.
(Ich weiß, es wird nicht in Python arbeiten 3)
global modpath
modname = 'os' #This can be any module name on the fly
#Create a file called "modname.py"
f=open("modname.py","w")
f.write("import "+modname+"\n")
f.write("modpath = "+modname+"\n")
f.close()
#Call the file with execfile()
execfile('modname.py')
print modpath
<module 'os' from 'C:\Python27\lib\os.pyc'>
habe ich versucht, von der „globalen“ Problem loszuwerden, aber Fälle gefunden, wo es nicht funktioniert Ich denke, "execfile ()" kann in Python 3 emuliert werden Da dies in einem Programm ist, kann es leicht in einem Verfahren oder ein Modul zur Wiederverwendung gestellt werden.
Wenn Sie möchten absoluten Pfad von Ihrem Skript wissen, die Sie verwenden können Pfad Objekt:
from pathlib import Path
print(Path().absolute())
print(Path().resolve('.'))
print(Path().cwd())
Gibt ein neuen Pfad Objekt das aktuelle Verzeichnis darstellt (wie durch os.getcwd zurückgegeben ())
Machen Sie den Pfad absolut keine Symlinks zu lösen. Ein neuer Weg Objekt zurückgegeben:
Wenn Sie das Paket Root-Pfad von jedem seiner Module, die folgenden Werke (getestet auf Python 3.6) abgerufen werden soll:
from . import __path__ as ROOT_PATH
print(ROOT_PATH)
Der Haupt __init__.py
Weg kann auch mit __file__
stattdessen referenziert werden.
Hope, das hilft!