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?

War es hilfreich?

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:

  1. den Pfad des gerufenen Skript zu finden
  2. den Pfad des aktuell ausgeführten Skripts zu finden
  3. 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>

 image description hier


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.

Quelle

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())

cwd () -Methode

  

Gibt ein neuen Pfad Objekt das aktuelle Verzeichnis darstellt (wie durch os.getcwd zurückgegeben ())

resolve () -Methode

  

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!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top