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
82 framelist.append(frame)
86 stack = stack_(sys._getframe(1))
88 if len(stack) < start + 1:
90 parentframe = stack[start]
93 module = inspect.getmodule(parentframe)
94 # `modname` can be None when frame is executed directly in console
95 # TODO(techtonik): consider using __main__
97 name.append(module.__name__)
99 if 'self' in parentframe.f_locals:
100 # I don't know any way to detect call from the object method
101 # XXX: there seems to be no way to detect static method call - it will
102 # be just a function call
103 name.append(parentframe.f_locals['self'].__class__.__name__)
104 codename = parentframe.f_code.co_name
106 fr = inspect.currentframe().f_back
107 lineno = [fr.f_lineno]
108 for i in range(20): # no more 20 for precaution
112 #print("*** frame locals %s" % str(fr.f_locals.keys()))
113 #print("*** frame globals %s" % str(fr.f_globals.keys()))
115 namesrc = fr.f_globals["__name__"]
116 if namesrc == "__main__":
117 namesrc = os.path.basename(fr.f_globals["__file__"])
118 lineno.insert(0, (namesrc + "[%s]" % fr.f_lineno))
120 lineno.insert(0, ("??", fr.f_lineno))
122 if codename != '<module>': # top level usually
123 name.append(codename) # function or a method
125 #print("lineno", lineno)
128 name[-1] += " // STACK: %s" % " ".join(lineno[0:-1])
131 return ".".join(name)
134 ##############################################################################
135 def example_of_use(toCall):
137 example of use caller_name_simple, or else
140 def one_method(self):
141 print("4- call in class %s" % toCall(0))
143 print("1- call in %s" % toCall(0)) # output from main to here
144 print("2- call in %s" % toCall(0))
145 print("3- call in %s" % toCall(1)) # output from main to caller
150 ##############################################################################
152 ##############################################################################
153 if __name__ == "__main__":
154 example_of_use(caller_name_simple)
155 example_of_use(caller_name_stack)
160 1- call in __main__.example_of_use[143]
161 2- call in __main__.example_of_use[144]
162 3- call in __main__[154]
163 4- call in class __main__.Dummy.one_method[141]
164 1- call in __main__.example_of_use // STACK: callerName.py[155]
165 2- call in __main__.example_of_use // STACK: callerName.py[155]
166 3- call in __main__ // STACK: callerName.py[155]
167 4- call in class __main__.Dummy.one_method // STACK: callerName.py[155] callerName.py[147]
171 # here default caller_name is user choice...
172 caller_name = caller_name_simple # not so verbose
173 # caller_name = caller_name_stack # more verbose, with stack