3 from opcode
import opname
6 __all__
= ["NameNotFound", "get_var_name", "get_src_loc"]
9 class NameNotFound(Exception):
13 _raise_exception
= object()
16 def get_var_name(depth
=2, default
=_raise_exception
):
17 frame
= inspect
.currentframe()
18 for _
in range(depth
):
22 call_index
= frame
.f_lasti
24 call_opc
= opname
[code
.co_code
[call_index
]]
25 if call_opc
in ("EXTENDED_ARG"):
29 if call_opc
not in ("CALL_FUNCTION", "CALL_FUNCTION_KW", "CALL_FUNCTION_EX", "CALL_METHOD"):
32 index
= call_index
+ 2
34 opc
= opname
[code
.co_code
[index
]]
35 if opc
in ("STORE_NAME", "STORE_ATTR"):
36 name_index
= int(code
.co_code
[index
+ 1])
37 return code
.co_names
[name_index
]
38 elif opc
== "STORE_FAST":
39 name_index
= int(code
.co_code
[index
+ 1])
40 return code
.co_varnames
[name_index
]
41 elif opc
== "STORE_DEREF":
42 name_index
= int(code
.co_code
[index
+ 1])
43 return code
.co_cellvars
[name_index
]
44 elif opc
in ("LOAD_GLOBAL", "LOAD_ATTR", "LOAD_FAST", "LOAD_DEREF",
45 "DUP_TOP", "BUILD_LIST"):
48 if default
is _raise_exception
:
54 def get_src_loc(src_loc_at
=0):
55 # n-th frame: get_src_loc()
56 # n-1th frame: caller of get_src_loc() (usually constructor)
57 # n-2th frame: caller of caller (usually user code)
58 # Python returns the stack frames reversed, so it is enough to set limit and grab the very
59 # first one in the array.
60 tb
= traceback
.extract_stack(limit
=3 + src_loc_at
)
61 return (tb
[0].filename
, tb
[0].lineno
)