2012-10-08 13 views
11

Funkcja Pythona ma obiekt kodu __code__.Uzyskiwanie funkcji Pythona dla obiektu kodu

A sys.settrace ślad frame ma obiekt kodowy f_code.

Dla tych wywołań funkcji śledzącej, w jaki sposób mogę uzyskać obiekt funkcji (i jego element __annotation__)?

Dotychczas metodą prób i błędów, mam:

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

To wydaje się działać dla funkcji, ale nie dla funkcji klasy członkowskich; gorzej, myli funkcje członka klasy z funkcjami najwyższego poziomu o tej samej nazwie.

(. Mam na Python 3.2.3 (Xubuntu) widzę, że Python 3.3 inspect moduł ma signature funkcji; będzie to powrót adnotacji dla obiektu kodu czy też zbyt potrzebują obiektu funkcji?)

Odpowiedz

5

Przez moduł inspect.getframeinfo. Mam na myśli - nie ma prostego sposobu robienia tego w Pythonie - Większość razy można uzyskać obiekt kodu, bez funkcji już, to poprzez instrospekcję klatki.

Funkcja getframeinfo funkcji Inspect zwraca pewne informacje o uruchomionej ramce, a następnie można pobrać obiekt funkcji, pobierając jego nazwę.

Tough jest zależna od implementacji i ma pewne wady:

>>> 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' 

Innym sposobem, ale nadal zależna od implementacji, jest użycie modułu GC (garbage collector), aby uzyskać odsyłających do wspomnianego obiektu kod.

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

- To dla Pythona 3 - dla Pythona 2 Jedna powinna zastąpić __code__ przez func_code

+0

katalogu '' inspect.getframeinfo' krotka w polu zakresie funkcji wydaje się być ciągiem, a nie obiekt funkcji. A podejście gc może zagrozić wielu polecającym? – Will

+0

Skończyło się na użyciu gc.get_referrers (...) [0] – Will

+1

Możesz dodać czek, aby sprawdzić, czy func_code/__ code__ jest obiektem kodu, który chcesz zrozumieć na liście. To nadal kończy się niepowodzeniem, jeśli wygenerujesz wiele funkcji za pomocą różne zamknięcia z tego samego obiektu kodu, np z dekoratorem. Przypuszczam, że można porównać f_locals przeciwko zawartość cell_contents z func_closure dla każdego ... –