2012-10-08 10 views
11

Eine Python-Funktion hat ein Codeobjekt __code__.Abrufen der Python-Funktion für ein Codeobjekt

Ein sys.settrace Trace frame hat ein f_code Code-Objekt.

Für diejenigen Aufrufe an den Tracer, die Funktionen sind, wie bekomme ich das Funktionsobjekt (und seine __annotation__ Mitglied)?

Bisher durch Versuch und Irrtum, ich habe:

if hasattr(frame.f_globals.get(frame.f_code.co_name),"__annotations__"): 

Dies scheint für Funktionen zu arbeiten, aber nicht für Klasse-Member-Funktionen; Schlimmer noch, es verwechselt Klassen-Member-Funktionen mit gleichnamigen Top-Level-Funktionen.

(. Ich bin auf Python 3.2.3 (Xubuntu) Ich sehe, dass Python 3.3 inspect Module eine signature Funktion hat, wird dies die Anmerkung für ein Code-Objekt zurück oder ist es auch ein Funktionsobjekt brauchen?)

Antwort

5

Durch das inspect.getframeinfo Modul. Ich meine - es gibt keine einfache Möglichkeit, das in Python zu tun - In den meisten Fällen können Sie das Code-Objekt erhalten, ohne die Funktion bereits, es ist durch Frame-Introspektion.

Die getframeinfo-Funktion von Inspect gibt einige Informationen über den ausgeführten Frame zurück, dann können Sie das Funktionsobjekt abrufen, indem Sie seinen Namen abrufen.

Tough ist diese Implementierung abhängig und haben einige Nachteile:

>>> import inspect 
>>> def a(): 
... return inspect.currentframe() 
... 

>>> inspect.getframeinfo(a()) 
Traceback(filename='<stdin>', lineno=2, function='a', code_context=None, index=None) 
>>> b = inspect.getframeinfo(a()) 
>>> b.function 
'a' 

Ein anderer Weg, aber immer noch abhängig von der Implementierung ist die gc-Modul (Garbage Collector) zu verwenden, Referrer zu erhalten Code zu dem Objekt.

>>> import gc 
>>> from types import FunctionType 
>>> def a(): pass 
... 
>>> code = a.__code__ 

>>> [obj for obj in gc.get_referrers(code) if isinstance(obj, FunctionType) ][0] 
<function a at 0x7f1ef4484500> 
>>> 

- Dies ist für Python 3 - für Python 2 ein __code__ von func_code

+0

der 'inspect.getframeinfo' Tupel' function' Feld scheint ersetzen sollte ein String zu sein, anstatt ein Funktionsobjekt. Und der GC-Ansatz riskiert mehrere Referrer? – Will

+0

Ich bin gelandet mit gc.get_referrers (...) [0] – Will

+1

Sie können eine Überprüfung hinzufügen, um zu sehen, ob func_code/__ code__ das Code-Objekt ist, das Sie in die Liste Verständnis. Dies schlägt immer noch fehl, wenn Sie mehrere Funktionen mit generieren unterschiedliche Schließungen vom selben Code-Objekt, z mit einem Dekorateur. Ich nehme an, man könnte die f_locals gegen die cell_contents der func_closure für jeden vergleichen ... –

Verwandte Themen