Wie kann ich die aktuellen Ausführung Modul oder Klassennamen in Python zugreifen?

StackOverflow https://stackoverflow.com/questions/602846

  •  03-07-2019
  •  | 
  •  

Frage

Ich möchte in der Lage sein, dynamisch aus einem importierten Modul die aktuelle Ausführung Modul oder Klassenname abzurufen. Hier ist ein Code:

foo.py:

def f():
    print __name__

bar.py:

from foo import f

def b(): f()

Das ist offensichtlich nicht funktioniert als __name__ der Name des Moduls ist, die die Funktion enthält. Was ich möchte, Zugang zum Innern des foo Modul sein, ist der Name des aktuellen Ausführungsmodul, das foo verwendet wird. So im Fall darüber bar werden würde, aber wenn ein anderes Modul foo importiert würde ich foo gerne dynamisch Zugang haben, um den Namen des Moduls.

Edit: Das inspect Modul sieht sehr vielversprechend, aber es ist nicht genau das, was ich suchte. Was ich erhofft war eine Art globalen oder Umwelt-Level-Variable, die ich, dass der Namen des aktuellen Ausführungsmodul enthalten würde zugreifen konnte. Nicht, dass ich bin nicht bereit, den Stapel zu durchqueren, diese Informationen zu finden - ich dachte nur, dass Python ausgesetzt hat, dass Daten bereits

.

Edit: Hier ist, wie ich versuche, diese zu verwenden. Ich habe zwei verschiedene Django-Anwendungen, die beide müssen Fehler protokollieren Datei. Lassen Sie uns sagen, dass sie „AppOne“ und „AppTwo“ bezeichnet werden. Ich habe auch einen Ort, an den Ich mag würde, diese Dateien protokollieren: „/home/hare/app_logs“. Bei jeder Anwendung an jedem beliebigen Punkt würde Ich mag Lage sein, mein Logger Modul zu importieren und die Log-Funktion aufrufen, die die Log-String-Datei schreibt. Aber was würde ich tun möchte, ist ein Verzeichnis unter app_logs erstellen, die die Namen der aktuellen Anwendung ( „AppOne“ oder „AppTwo“), so dass jede Protokolldateien der Anwendung in ihren jeweiligen Protokoll Verzeichnisse gehen.

Um dies zu tun, dachte ich, dass der beste Weg wäre, der Logger-Modul Zugang zu haben, um eine Art globale Variable, die der aktuellen Anwendung Namen bezeichnet, wie es für die Kenntnis der Position des übergeordneten Protokollverzeichnis verantwortlich ist und die Schaffung von die Logging-Verzeichnis der Anwendung, wenn es noch nicht vorhanden ist.

War es hilfreich?

Lösung

Aus dem Kommentar -. Nicht die Frage

  

Ich bin einfach gespannt, ob das, was ich versuche möglich zu tun ist.

Die Antwort auf „ist es möglich,“ immer „ja“. Immer. Es sei denn, Ihre Frage beinhaltet eine Zeitreise, Anti-Schwerkraft oder ständige Bewegung.

Da die Antwort ist immer „ja“ lautet, Ihre Frage ist schlecht ausgebildet. Die eigentliche Frage lautet: „Was ist ein guter Weg, um meinen Logging-Modul den Namen des Kunden kennt zu haben?“ oder so ähnlich.

Die Antwort ist „Nehmen Sie es als Parameter.“ Verwirren Sie nicht um mit Inspektion oder auf der Suche nach einem geheimnisvollen Globals oder anderen Tricks.

Folgen Sie einfach dem Designmuster von logging.getLogger () und explizit genannten Logger verwenden. Ein gemeinsames Idiom ist die folgende

logger= logging.getLogger( __name__ )

Das Griffe fast alle Log-Namensgebung perfekt.

Andere Tipps

Dies sollte das aktuelle Modul zur Referenzierung arbeiten:

import sys
sys.modules[__name__]

Die „aktuell ausgeführte Modul“ eindeutig ist foo, wie das ist, was die Funktion enthält derzeit läuft - ich denke, eine bessere Beschreibung, was Sie wollen, ist das Modul der sofortigen Anrufers foo (die selbst foo sein kann, wenn Sie anrufen af () aus einer Funktion in foo durch eine Funktion in bar genannt. Wie weit Sie hängt davon ab, gehen will, was Sie wollen, dass diese für.

In jedem Fall vorausgesetzt, Sie den unmittelbaren Aufrufer möchten, können Sie diese erhalten, indem man den Call-Stack Fuß nach oben. Dies kann durch den Aufruf von sys._getframe erreicht werden, mit der aprropriate Anzahl der Ebenen gehen.

def f():
    caller = sys._getframe(1)  # Obtain calling frame
    print "Called from module", caller.f_globals['__name__']

[Bearbeiten] : Eigentlich die zu inspizieren Modul, wie oben vorgeschlagen, ist wahrscheinlich ein sauberer Weg, um den Stapelrahmen zu erhalten. Der entsprechende Code ist:

def f():
    caller = inspect.currentframe().f_back
    print "Called from module", caller.f_globals['__name__']

(sys._getframe wird dokumentiert, wie für den internen Gebrauch zu sein - das überprüfen Modul ist ein zuverlässiger API)

Ich denke, was Sie verwenden möchten, ist die Modul inspizieren, inspizieren die python-Laufzeit-Stack. Schauen Sie sich diese Tutorial . Ich denke, es gibt ein fast genau Beispiel dafür, was Sie tun mögen.

__file__ ist der Pfad des aktuellen Moduls der Anruf erfolgt.

Um einen Verweis auf das "__main__" -Modul, wenn sie in ein anderes zu erhalten:

import sys
sys.modules['__main__']

dann um das Modul des Dateipfad zu erhalten, die ihren Namen enthält:

sys.modules['__main__'].__file__

Wenn im "__main__" -Modul, verwenden Sie einfach: __file__

Um nur die Dateinamen aus dem Dateipfad zu erhalten:

import os
os.path.basename(file_path)

Um die Dateinamen von seiner Erweiterung zu trennen:

file_name.split(".")[0]

Um den Namen einer Klasseninstanz zu erhalten:

instance.__class__.__name__

Um den Namen einer Klasse zu erhalten:

class.__name__

Ich glaube nicht, das möglich ist, da diese aus foo Anwendungsbereich ist. foo nur bewusst sein, ihren internen Anwendungsbereich, da es durch unzählige andere Module und Anwendungen aufgerufen werden wird.

Mit __file__ allein gibt Ihnen einen relativen Pfad für das Hauptmodul und einen absoluten Pfad für importierte Module. Im Bewusstsein diesen können wir die Moduldatei ständig oder so mit einer wenig Hilfe von unseren os.path Tool.

Für Dateinamen nur __file__.split(os.path.sep)[-1] verwenden.

Für eine vollständige Pfad Verwendung os.path.abspath(__file__).

Demo:

/tmp $ cat f.py
from pprint import pprint
import os
import sys

pprint({
    'sys.modules[__name__]': sys.modules[__name__],
    '__file__': __file__,
    '__file__.split(os.path.sep)[-1]': __file__.split(os.path.sep)[-1],
    'os.path.abspath(__file__)': os.path.abspath(__file__),
})

/tmp $ cat i.py
import f

Ergebnisse:

## on *Nix ##

/tmp $ python3 f.py
{'sys.modules[__name__]': <module '__main__' from 'f.py'>,
 '__file__': 'f.py',
 '__file__.split(os.path.sep)[-1]': 'f.py',
 'os.path.abspath(__file__)': '/tmp/f.py'}

/tmp $ python3 i.py
{'sys.modules[__name__]': <module 'f' from '/tmp/f.pyc'>,
 '__file__': '/tmp/f.pyc',
 '__file__.split(os.path.sep)[-1]': 'f.pyc',
 'os.path.abspath(__file__)': '/tmp/f.pyc'}

## on Windows ##

PS C:\tmp> python3.exe f.py
{'sys.modules[__name__]': <module '__main__' from 'f.py'>,
 '__file__': 'f.py',
 '__file__.split(os.path.sep)[-1]': 'f.py',
 'os.path.abspath(__file__)': 'C:\\tools\\cygwin\\tmp\\f.py'}

PS C:\tmp> python3.exe i.py
{'sys.modules[__name__]': <module 'f' from 'C:\\tools\\cygwin\\tmp\\f.py'>,
 '__file__': 'C:\\tools\\cygwin\\tmp\\f.py',
 '__file__.split(os.path.sep)[-1]': 'f.py',
 'os.path.abspath(__file__)': 'C:\\tools\\cygwin\\tmp\\f.py'}

Wenn Sie das ‚.py‘ abzustreifen wollen über das Ende, können Sie das leicht tun. (Aber vergessen Sie nicht, dass Sie stattdessen ein ‚.pyc‘ laufen.)

Es ist schon eine Weile her, seit ich Python getan habe, aber ich glaube, dass Sie Zugriff auf die globalen Variablen und Einheimischer von einem Anrufer über die Zurückverfolgungs .

Wenn Sie nur den Namen der Datei wollen:

file_name = __file__.split("/")[len(__file__.split("/"))-1]

Um den aktuellen Datei-Modul zu erhalten, einen Ordner enthält, hier ist das, was für mich gearbeitet:

 import os
 parts = os.path.splitext(__name__)
 module_name = parts[len(parts) - 2]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top