16

Python関数にはコードオブジェクトがあります__code__

sys.settraceトレースにframef_codeコードオブジェクトがあります。

関数であるトレーサーへの呼び出しの場合、関数オブジェクト(およびその__annotation__メンバー)を取得するにはどうすればよいですか?

これまでのところ、試行錯誤によって、私は次のことを行っています。

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

これは関数では機能するようですが、クラスメンバー関数では機能しません。さらに悪いことに、クラスメンバー関数を同じ名前のトップレベル関数と混同します。

(私はPython 3.2.3(Xubuntu)を使用しています。Python3.3inspectモジュールにsignature関数があることがわかります。これにより、コードオブジェクトの注釈が返されますか、それとも関数オブジェクトが必要ですか?)

4

2 に答える 2

7

inspect.getframeinfoモジュールを介して。つまり、Pythonでそれを行う簡単な方法はありません。ほとんどの場合、関数がなくてもコードオブジェクトを取得できるのは、フレームのイントロスペクションによるものです。

Inspectのgetframeinfo関数は、実行中のフレームに関する情報を返します。次に、その名前を取得することで関数オブジェクトを取得できます。

これは実装に依存し、いくつかの欠点があります。

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

もう1つの方法は、実装に依存しますが、gcモジュール(ガベージコレクター)を使用して、リファラーを上記のコードオブジェクトに取得することです。

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

-これはPython3用です-Python2の場合は次のように置き換える必要__code__がありますfunc_code

于 2012-10-08T18:12:43.913 に答える
1

モジュールまたはクラスの属性として関数オブジェクトを取得できます。

import inspect
import sys


def frame_to_func(frame):
    func_name = frame.f_code.co_name
    if "self" in frame.f_locals:
        return getattr(frame.f_locals["self"].__class__, func_name)
    else:
        return getattr(inspect.getmodule(frame), func_name)


def tracefunc(frame, event, arg):
    if event in ['call', 'return']:
        func_obj = frame_to_func(frame)
        print(f"{event} {frame.f_code.co_name} {func_obj.__annotations__}")


def add(x: int, y: int) -> int:
    return x+y


if __name__ == '__main__':
    sys.settrace(tracefunc)
    add(1, 2)
    sys.settrace(None)

出力: call add {'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}

解決策は、この質問に触発されています。

于 2020-04-24T09:53:09.063 に答える