Python调试技术之变量名称获取 郝伟 2021/03/29 [TOC]
1. 问题
这样的代码相信大家都很常用:
a, b = 10, 20
print('a=', a)
print('b=', a)
其作用是在输出时显示变量a的名称,我们可否简化成:
a, b = 10, 20
show(a)
show(b)
然后显示同样的内容呢?
2. 示例及输出效果
以下代码定义了一个变量并进行调用输出:
s1 = pandas.DataFrame([1, 2, 3], list('abc'))
show(s1.index)
输出:
s1.index = Index(['a', 'b', 'c'], dtype='object')
可见,show函数能够获得输入变量的名称,并自动输出,达到了我们预期的目标。
3. 全代码
代码中实际上共提供了三种方法,只有最后一种最完善。 解释都放在代码中了,不再细表。
import matplotlib.pyplot as plt
import pandas as pd
import re
import traceback
import inspect
pattren = re.compile(r'[\W+\w+]*?get_variable_name\((\w+)\)')
__get_variable_name__ = []
def get_variable_name(x):
global __get_variable_name__
if not __get_variable_name__:
__get_variable_name__ = pattren.findall(traceback.extract_stack(limit=2)[0][3])
return __get_variable_name__.pop(0)
def retrieve_variable_name(var):
"""
获得变量var的名称,这个名称是最开始定义时的名称。
获取原理是利用变量存储栈。
如果获取失败则返回长度为0的字符串。
:参数 var: 待获得名称的变量。
:返回类型: 字符串
"""
for fi in reversed(inspect.stack()):
names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
if len(names) > 0:
return names[0]
return ''
def test0():
print('hello')
plt.plot([1,2, 3], [4,5,6])
plt.plot(range(100),
[i * i for i in range(100)])
plt.plot(1,2)
plt.show()
# 反射有四个方法:hasattr、getattr、setattr、delattr,比较常用的是前两种,一般会结合起来用。
def show(obj1, prop_name):
# print('name:', get_variable_name(obj1))
# print('name:', retrieve_variable_name(obj1))
title=retrieve_variable_name(obj1)+'.'+prop_name+':'
if hasattr(obj1, prop_name):
v = getattr(obj1, prop_name)
print(title, v)
else:
print(title)
s1 = pd.DataFrame([1, 2, 3], list('abc'))
print(s1.index)
print(getattr(s1, 'index'))
show(s1, 'index')
# print('s1:', get_variable_name(s1))
print('sig:', inspect.signature(retrieve_variable_name))
print('1:', retrieve_variable_name(s1.index))
#print('2:', retrieve_variable_name(s1.index))
# ★★★★ 真正可用的代码 ★★★★
# 参考: http://blog.csdn.net/chunyexiyu
def retrieve_name_ex(var):
'''
实现的原理是利用inspect获得函数的源代码,从而取得变量的字符串。
'''
stacks = inspect.stack()
try:
code = stacks[2].code_context[0] # 获得调用行的代码
callFunc = stacks[1].function # 获得调用的函数名
# 获得函数中起始索引位置,以取得变量名称的字符串
startIndex = code.index("(", code.index(callFunc) + len(callFunc)) + 1
endIndex = code.index(")", startIndex)
name=code[startIndex:endIndex].strip() # 获得变量名称
return name
except:
return ""
def show(var):
print(retrieve_name_ex(var), '=', var)
outputVar(s1.index)
4. 结论
通过本文,我们可以掌握获得一个变量的完整名称的几种方法。在此基础之上,我们可以利用 inspect 库,实现对代码进行过程中的全面监视,从而可以实现更多更强大的能力。
5. 参考资料
Python获取变量名称,https://blog.csdn.net/chunyexiyu/article/details/84879295 Python 中的反射操作,https://zhuanlan.zhihu.com/p/99150129