4 # https://gist.github.com/techtonik/2151727
5 # Public Domain, i.e. feel free to copy/paste
6 # Considered a hack in Python 2
15 ##############################################################################
16 def caller_name_simple(skip=1):
18 Get a name of a caller in the format module.class.method
20 'skip' specifies how many levels of stack to skip while getting caller
21 name. skip=1 means 'who calls me', skip=2 'who calls my caller' etc.
23 An empty string is returned if skipped levels exceed stack height
29 framelist.append(frame)
33 stack = stack_(sys._getframe(1))
35 if len(stack) < start + 1:
37 parentframe = stack[start]
40 module = inspect.getmodule(parentframe)
41 # `modname` can be None when frame is executed directly in console
42 # TODO(techtonik): consider using __main__
44 name.append(module.__name__)
46 if "self" in parentframe.f_locals:
47 # I don't know any way to detect call from the object method
48 # XXX: there seems to be no way to detect static method call - it will
49 # be just a function call
50 name.append(parentframe.f_locals["self"].__class__.__name__)
51 codename = parentframe.f_code.co_name
53 fr = inspect.currentframe().f_back
54 for i in range(skip): # no more 20 for precaution
60 if codename != "<module>": # top level usually
63 name[-1] += "[%s]" % str(lineno) # function or a method
68 ##############################################################################
69 def caller_name_stack(skip=1):
71 Get a name of a caller in the format module[no].class[no].method[no]
72 where [no] is line nunber in source file(s)
74 'skip' specifies how many levels of stack to skip while getting caller
75 name. skip=1 means 'who calls me', skip=2 'who calls my caller' etc.
77 An empty string is returned if skipped levels exceed stack height
83 framelist.append(frame)
87 stack = stack_(sys._getframe(1))
89 if len(stack) < start + 1:
91 parentframe = stack[start]
94 module = inspect.getmodule(parentframe)
95 # `modname` can be None when frame is executed directly in console
96 # TODO(techtonik): consider using __main__
98 name.append(module.__name__)
100 if "self" in parentframe.f_locals:
101 # I don't know any way to detect call from the object method
102 # XXX: there seems to be no way to detect static method call - it will
103 # be just a function call
104 name.append(parentframe.f_locals["self"].__class__.__name__)
105 codename = parentframe.f_code.co_name
107 fr = inspect.currentframe().f_back
108 lineno = [fr.f_lineno]
109 for i in range(20): # no more 20 for precaution
113 # print("*** frame locals %s" % str(fr.f_locals.keys()))
114 # print("*** frame globals %s" % str(fr.f_globals.keys()))
116 namesrc = fr.f_globals["__name__"]
117 if namesrc == "__main__":
118 namesrc = os.path.basename(fr.f_globals["__file__"])
119 lineno.insert(0, (namesrc + "[%s]" % fr.f_lineno))
121 lineno.insert(0, ("??", fr.f_lineno))
123 if codename != "<module>": # top level usually
124 name.append(codename) # function or a method
126 # print("lineno", lineno)
127 # print("name", name)
129 name[-1] += " // STACK: %s" % " ".join(lineno[0:-1])
132 return ".".join(name)
135 ##############################################################################
136 def example_of_use(toCall):
138 example of use caller_name_simple, or else
142 def one_method(self):
143 print("4- call in class %s" % toCall(0))
145 print("1- call in %s" % toCall(0)) # output from main to here
146 print("2- call in %s" % toCall(0))
147 print("3- call in %s" % toCall(1)) # output from main to caller
152 ##############################################################################
154 ##############################################################################
155 if __name__ == "__main__":
156 example_of_use(caller_name_simple)
157 example_of_use(caller_name_stack)
162 1- call in __main__.example_of_use[143]
163 2- call in __main__.example_of_use[144]
164 3- call in __main__[154]
165 4- call in class __main__.Dummy.one_method[141]
166 1- call in __main__.example_of_use // STACK: callerName.py[155]
167 2- call in __main__.example_of_use // STACK: callerName.py[155]
168 3- call in __main__ // STACK: callerName.py[155]
169 4- call in class __main__.Dummy.one_method // STACK: callerName.py[155] callerName.py[147]
173 # here default caller_name is user choice...
174 caller_name = caller_name_simple # not so verbose
175 # caller_name = caller_name_stack # more verbose, with stack