2010-01-04 16 views
8

Bei einem Rahmenobjekt muss das entsprechende Modulobjekt abgerufen werden. Mit anderen Worten, implementieren callers_module so das funktioniert.Abrufen des Modulobjekts aus dem Stapelrahmen

import sys 
from some_other_module import callers_module 
assert sys.modules[__name__] is callers_module() 

(Das wäre gleichbedeutend, weil ich einen Stack-Trace in der Funktion für diesen Testfall generieren Die Importe sind es einfach, dass beispielsweise vollständig und überprüfbar zu machen, und verhindert callers_module daran, die Verknüpfung von __name__ verwenden, da es in einem anderen Modul ist)

ich habe dies versucht.

import inspect 
def callers_module(): 
    return inspect.currentframe().f_back 

der ein Frame-Objekt erhält, auf dem f_code gibt mir einen Code Objekt, aber ich kann dich nicht finden t wie man das entsprechende Modul oder seinen Namen bekommt (zur Verwendung mit sys.modules). Wenn ich Funktionsobjekte bekommen könnte, hätten diese ein Attribut __module__ (und auch Code-Objekte), aber das ist nicht im Frame vorhanden. Tatsächlich gehören nicht alle Codeobjekte zu Funktionsobjekten, wie der Code für meinen Testfall (mit Assert, oben). Das gleiche gilt für Frame/Code-Objekte, die kein Modul — haben, aber viele von ihnen tun dies, und in meinem Fall werden sie dies tun, so dass sie nicht behandelt werden müssen; Eine einfache None oder Ausnahme ist in diesem Fall jedoch auch in Ordnung.

Es fühlt sich an, als ob ich etwas Einfaches vermisse. Was muss getan werden, damit dies funktioniert?

Antwort

2
import inspect 
def callers_module(): 
    module = inspect.getmodule(inspect.currentframe().f_back) 
    return module 
5

Während inspect.getmodule funktioniert gut, und ich war in der Tat an der falschen Stelle suchen, um es zu finden, fand ich eine etwas bessere Lösung für mich:

def callers_module(): 
    module_name = inspect.currentframe().f_back.f_globals["__name__"] 
    return sys.modules[module_name] 

Es inspect.currentframe noch verwendet (das bevorzuge ich über den genau identischen sys._getframe), aber nicht inspect das Modul-Dateinamen-Mapping (in inspect.getmodule) aufrufen.

Darüber hinaus ist diese Frage eine interessante Art und Weise zu manage __all__ inspiriert:

from export import export 

@export 
class Example: pass 

@export 
def example: pass 

answer = 42 
export.name("answer") 

assert __all__ == ["Example", "example", "answer"] 
+0

Nun wünsche ich mir Module aufrufbar machen könnte und das obige Beispiel vereinfachen: http://stackoverflow.com/questions/1060796/callable-modules –

+2

Vorsicht, wenn Sie nach dem String mit dem Modulnamen suchen. Es wird nicht wie erwartet funktionieren, wenn das Modul als [Top-Level-Skript] (https://docs.python.org/3/library/__main__.html) ausgeführt wird, weil dann '' __name__' 'immer sein wird '' __main__''. Um alle Fälle abzudecken, ist es am besten, 'inspect.getmodule() .__ spec __. Name'' zu verwenden, das den Namen des realen Moduls mit sich bringt, auch wenn es sich um das Skript der obersten Ebene handelt. –

Verwandte Themen