Getting the Python function for a code object

前端 未结 2 1162
借酒劲吻你
借酒劲吻你 2020-12-30 06:41

A Python function has a code object __code__.

A sys.settrace trace frame has a f_code code object.

For th

相关标签:
2条回答
  • 2020-12-30 07:02

    You can retrieve the function-object as an attribute of the module or the class:

    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)
    

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

    The solution is inspired by this question.

    0 讨论(0)
  • 2020-12-30 07:19

    Through the inspect.getframeinfo module. I mean -- there is no straightforward way of doing that in Python -- Most times you can get hold of the code object, without having the function already, it is through frame instrospection.

    Inspect's getframeinfo function does return some information about the frame being run, then you can retrieve the function object by getting its name.

    Tough this is implementation dependent and have some drawbacks:

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

    Another way, but still implementation dependent, is to use the gc module (garbage collector) to get referrers to said code object.

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

    -- This is for Python 3 - for Python 2 one should replace __code__ by func_code

    0 讨论(0)
提交回复
热议问题