it-swarm.com.de

Wie rufe ich den Pfad eines Moduls ab?

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

Wie rufe ich den Pfad eines Moduls in Python ab?

664
Cheery
import a_module
print(a_module.__file__)

Gibt Ihnen tatsächlich den Pfad zur geladenen .pyc-Datei an, zumindest unter Mac OS X. Ich schätze, Sie können Folgendes tun:

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.

781
orestis

Es gibt ein inspect Modul in Python.

Offizielle Dokumentation

Das Inspect-Modul bietet verschiedene nützliche Funktionen, mit denen Sie Informationen über Live-Objekte wie Module, Klassen, Methoden, Funktionen, Tracebacks, Frame-Objekte und Code-Objekte abrufen können. Sie können damit beispielsweise den Inhalt einer Klasse untersuchen, den Quellcode einer Methode abrufen, die Argumentliste für eine Funktion extrahieren und formatieren oder alle Informationen abrufen, die Sie zum Anzeigen 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'
232
SummerBreeze

Wie die anderen Antworten bereits sagten, ist der beste Weg, dies zu tun, __file__ (weiter unten noch einmal demonstriert). Es gibt jedoch eine wichtige Einschränkung: __file__ ist NICHT vorhanden, wenn Sie das Modul alleine ausführen (d. H. Als __main__).

Angenommen, Sie haben zwei Dateien (beide befinden sich auf Ihrem PYTHONPATH):

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

und

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

Wenn Sie foo.py ausführen, erhalten Sie folgende 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 versuchen, bar.py alleine 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 

Hoffe das hilft. Diese Einschränkung hat mich viel Zeit und Verwirrung gekostet, als ich die anderen vorgestellten Lösungen getestet habe.

66
mcstrother

Ich werde auch versuchen, einige Variationen dieser Frage anzusprechen:

  1. finden des Pfades des aufgerufenen Skripts
  2. suche nach dem Pfad des aktuell ausgeführten Skripts
  3. finden des Verzeichnisses des aufgerufenen Skripts

(Einige dieser Fragen wurden auf SO gestellt, aber als Duplikate geschlossen und hier umgeleitet.)

Vorsichtsmaßnahmen bei der Verwendung von __file__

Für ein Modul, das Sie importiert haben:

import something
something.__file__ 

gibt den absoluten Pfad des Moduls zurück. In Anbetracht des folgenden Skripts foo.py:

#foo.py
print '__file__', __file__

Wenn Sie es mit 'python foo.py' aufrufen, wird einfach 'foo.py' zurückgegeben. Wenn Sie einen Shebang hinzufügen:

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

und rufen Sie es mit ./foo.py auf, es wird './foo.py' zurückgegeben. Aufruf aus einem anderen Verzeichnis (z. B. foo.py in die Verzeichnisleiste einfügen), dann entweder aufrufen

python bar/foo.py

oder fügen Sie einen Shebang hinzu und führen Sie die Datei direkt aus:

bar/foo.py

gibt "bar/foo.py" (den relativen Pfad) zurück.

Das Verzeichnis finden

Wenn Sie nun von dort aus nach dem Verzeichnis suchen, kann os.path.dirname(__file__) auch schwierig sein. Zumindest auf meinem System gibt es eine leere Zeichenfolge zurück, wenn Sie sie aus demselben Verzeichnis wie die Datei aufrufen. Ex.

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

wird ausgeben:

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

Mit anderen Worten, es wird eine leere Zeichenfolge zurückgegeben, sodass dies nicht zuverlässig erscheint, wenn Sie sie für die aktuelle Datei verwenden möchten (im Gegensatz zur Datei eines importierten Moduls). Um dies zu umgehen, können Sie es in einen Aufruf von abspath einschließen:

# 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__))

was gibt so etwas aus 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 () keine Symlinks auflöst. Wenn Sie dies tun möchten, verwenden Sie stattdessen realpath (). Wenn Sie beispielsweise einen Symlink file_import_testing_link erstellen, der auf file_import_testing.py mit folgendem Inhalt verweist:

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

beim Ausführen werden absolute Pfade wie folgt ausgegeben:

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 mit dem inspect Modul.

Dies scheint für importierte Module gut und sehr präzise zu funktionieren:

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

gibt gehorsam den absoluten Pfad zurück. Um den Pfad des aktuell ausgeführten Skripts zu finden, konnte ich ihn jedoch nicht verwenden.

36
jpgeek

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 - hier ):

import imp
imp.find_module("os")

Es gibt 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 Methode "inspect" besteht darin, dass Sie das Modul nicht importieren müssen, damit es funktioniert, und Sie können eine Zeichenfolge in der Eingabe verwenden. Nützlich, wenn Sie beispielsweise Module überprüfen, die in einem anderen Skript aufgerufen wurden.

EDIT:

In python3 sollte das importlib -Modul Folgendes tun:

Doc 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, wird sys.modules [name]. spec zurückgegeben. Wenn dies auf None gesetzt ist, wird ValueError ausgelöst. Befindet sich das Modul nicht in sys.modules, wird sys.meta_path nach einer geeigneten Spezifikation mit dem Wert 'path' durchsucht, der den Findern übergeben wird. Keine wird zurückgegeben, wenn keine Spezifikation gefunden werden konnte.

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

Die Argumente für Name und Paket entsprechen denen von importlib.import_module (). Mit anderen Worten, relative Modulnamen (mit führenden Punkten) funktionieren.

29
PlasmaBinturong

Das war trivial.

Jedes Modul hat eine __file__ -Variable, die den relativen Pfad anzeigt, von dem aus Sie sich gerade befinden.

Daher ist es einfach, ein Verzeichnis für das Modul zu erhalten, um es zu benachrichtigen:

os.path.dirname(__file__)
19
Cheery
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
17
vinoth

Befehlszeilenprogramm

Sie können es zu einem Befehlszeilenprogramm optimieren,

python-which <package name>

enter image description here


Erstelle /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__)

Mach es ausführbar

Sudo chmod +x /usr/local/bin/python-which
9
Jossef Harush
import module
print module.__path__

Pakete unterstützen ein weiteres spezielles Attribut, __path__. Dies wird als Liste initialisiert, die den Namen des Verzeichnisses enthält, in dem sich der __init__.py des Pakets befindet, bevor der Code in dieser Datei ausgeführt wird. Diese Variable kann geändert werden. Dies wirkt sich auf zukünftige Suchvorgänge nach Modulen und Unterpaketen aus, die im Paket enthalten sind.

Obwohl diese Funktion nicht oft benötigt wird, kann sie verwendet werden, um die in einem Paket enthaltenen Module zu erweitern.

Quelle

8
Lukas Greblikas

Daher habe ich ziemlich viel Zeit damit verbracht, dies mit py2exe zu tun. Das Problem bestand darin, den Basisordner des Skripts abzurufen, unabhängig davon, ob es als python Skript oder als ausführbare py2exe-Datei ausgeführt wurde. Auch damit es funktioniert, ob es vom aktuellen Ordner, einem anderen Ordner oder (am schwierigsten) vom Pfad des Systems aus ausgeführt wurde.

Schließlich habe ich diesen Ansatz verwendet und sys.frozen als Indikator für die Ausführung in py2exe verwendet:

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__))
7
uri

sie können einfach Ihr Modul importieren und dann auf den Namen klicken, um den vollständigen Pfad zu erhalten

>>> import os
>>> os
<module 'os' from 'C:\\Users\\Hassan Ashraf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\os.py'>
>>>
5
Hassan Ashraf

Wenn die einzige Einschränkung bei der Verwendung von __file__ darin besteht, dass das relative Verzeichnis aktuell ist (dh, wenn es als Skript in demselben Verzeichnis ausgeführt wird, in dem sich das Skript befindet), lautet die einfache Lösung:

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 Aufruf von dirname(). Es setzt das Verzeichnis auf ., was aktuelles Verzeichnis bedeutet und ist ein gültiges Verzeichnis für jede pfadbezogene Funktion.

Daher wird die Verwendung von abspath() nicht wirklich benötigt. Wenn Sie es dennoch verwenden, wird der Trick nicht benötigt: abspath() akzeptiert leere Pfade und interpretiert es ordnungsgemäß als das aktuelle Verzeichnis.

3
MestreLion

Ich möchte mit einem allgemeinen Szenario (in Python 3) einen Beitrag leisten und einige Ansätze dafür untersuchen.

Die eingebaute Funktion open () akzeptiert entweder den relativen oder den absoluten Pfad als erstes Argument. Der relative Pfad wird als relativ zum aktuellen Arbeitsverzeichnis behandelt, daher wird empfohlen, den absoluten Pfad an die Datei zu übergeben.

Einfach gesagt, wenn Sie eine Skriptdatei mit dem folgenden Code ausführen, ist nicht garantiert, dass die example.txt -Datei in derselben erstellt wird Verzeichnis, in dem sich die Skriptdatei befindet:

with open('example.txt', 'w'):
    pass

Um diesen Code zu korrigieren, müssen wir den Pfad zum Skript ermitteln und ihn absolut machen. Um sicherzustellen, dass der Pfad absolut ist, verwenden wir einfach die Funktion os.path.realpath () . Um den Pfad zum Skript zu erhalten, gibt es mehrere allgemeine Funktionen, die verschiedene Pfadergebnisse zurückgeben:

  • os.getcwd()
  • os.path.realpath('example.txt')
  • sys.argv[0]
  • __file__

Beide Funktionen os.getcwd () und os.path.realpath () geben Pfadergebnisse basierend auf dem aktuellen Arbeitsverzeichnis zurück . Im Allgemeinen nicht das, was wir wollen. Das erste Element der Liste sys.argv ist der Pfad des Root-Skripts (des Skripts, das Sie ausführen), unabhängig davon, ob Sie die Liste in der Liste aufrufen Root-Skript selbst oder in einem seiner Module. In manchen Situationen kann es nützlich sein. Die Variable _ FILE _ enthält den Pfad des Moduls, von dem aus es aufgerufen wurde.


Der folgende Code erstellt korrekt eine Datei example.txt in demselben 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
3
Jeyekomon

Innerhalb von Modulen eines python -Pakets musste ich auf eine Datei verweisen, die sich im selben Verzeichnis wie das Paket befand. Ex.

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

Also musste ich oben maincli.py vom Modul my_lib_a.py aufrufen und wusste, dass sich top_package und maincli.py im selben Verzeichnis befinden. So erhalte ich den Pfad zu 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

Aufgrund der Veröffentlichung von PlasmaBinturong habe ich den Code geändert.

1
Al Conrad

Wenn Sie dies dynamisch in einem "Programm" tun möchten, versuchen Sie diesen Code:
Mein Punkt ist, dass Sie möglicherweise nicht den genauen Namen des Moduls kennen, um es "fest zu codieren". Es kann aus einer Liste ausgewählt werden oder gerade nicht ausgeführt werden, um __file__ zu verwenden.

(Ich weiß, es wird nicht funktionieren in Python 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'>

Ich habe versucht, das "globale" Problem loszuwerden, habe aber Fälle gefunden, in denen es nicht funktioniert hat. Ich denke, "execfile ()" kann in Python 3 emuliert werden in einer Methode oder einem Modul zur Wiederverwendung.

1
Robin Randall

Wenn Sie den absoluten Pfad Ihres Skripts kennen möchten, können Sie Path object verwenden:

from pathlib import Path

print(Path().absolute())
print(Path().resolve('.'))
print(Path().cwd())

cwd () Methode

Gibt ein neues Pfadobjekt zurück, das das aktuelle Verzeichnis darstellt (wie von os.getcwd () zurückgegeben).

resolve () Methode

Machen Sie den Pfad absolut und lösen Sie alle Symlinks auf. Ein neues Pfadobjekt wird zurückgegeben:

1
Vlad Bezden

Wenn Sie den Stammpfad des Pakets von einem seiner Module abrufen möchten, funktioniert Folgendes (getestet auf Python 3.6):

from . import __path__ as ROOT_PATH
print(ROOT_PATH)

Auf den Hauptpfad __init__.py kann auch verwiesen werden, indem stattdessen __file__ verwendet wird.

Hoffe das hilft!

0
fr_andres