'finding the caller object given its name only

I want to find the caller callable from within the called object, without explcitely forwarding the caller to the called as an object.

My current code looks something like this:

class Boo:

@classmethod
def foo(cls, aa, b2=2):
    _ret = aa + b2
    autolog(fn=Boo.foo, values={"input": locals(), "output": _ret}, message="This is what it should look like")
    autolog_nameless(values={"input": locals(), "output": _ret}, message="This would be convenient")
    return _ret 

and yields

DEBUG | Boo.foo with aa=3.14159, b2=2 yields 5.14159. Message: This is what it should look like
DEBUG | cls=<class '__main__.Boo'>, aa=3.14159, b2=2, _ret=5.14159 yields 5.14159. Message: This would be convenient

The method autolog gets the locals() and the caller method fn, and parses them using the signature of the caller. This works nice and provides the desired output, but requires passing the caller as an object - something I'd like to avoid as I'm refractoring to include this feature and have about 1000 places to modify.

What I'd like to achieve is: pass locals() only; get the name of the caller within autolog_nameless, using inspect.stack()[1][3] or rather inspect.currentframe().f_back.f_code.co_name (latter has much less overhead), and using this - an possibly the information in locals() - find the caller object to inspect it for its signature.

The method autolog_nameless gets cls, actually the class as part of locals() (or would get self if the caller was a simple method), but I can't really do anything with it.

I'd think all the information required is given, but I just can't find a solution. Any help is greatly appreciated.



Solution 1:[1]

As it turns out it's quite simple: listing the methods of the class object found in locals() and searching by name should do the trick.

Code, without error checking:

# getting all methods of the class
methods = inspect.getmembers(locals()['cls'], predicate=inspect.ismethod)

# finding the callers name; won't work within the list comprehension for scope issues
_name = inspect.currentframe().f_back.f_code.co_name

# methods is a list of tuples, each tuple holds the name and the method object
fn = [x for x in methods if x[0] == _name][0][1]

and fn is the caller object to check the signature.

Note, locals()['cls'] works here as in the example we have a classmethod, but this is just the object that the called method belongs to.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jake77