如何从Python对象的内存地址获取对应的变量名?
如何通过内存地址获取对应的Python变量名
首先还原你给出的测试场景:
>>> class mytest(): ... pass ... >>> x = mytest() >>> id(x) 140696428216768 >>> x <__main__.mytest object at 0x7ff670a001c0> >>> int(0x7ff670a001c0) 140696428216768
你尝试用ctypes获取对象,但只能拿到实例本身,没法直接得到变量名:
>>> import ctypes >>> ctypes.cast(140696428216768, ctypes.py_object).value <__main__.mytest object at 0x7ff670a001c0> >>> ctypes.cast('0x7ff670a001c0', ctypes.py_object).value Segmentation fault # 这里要注意:cast需要传整数地址,不能传字符串
核心原因
Python里的变量名本质是指向对象的引用,对象本身并不存储任何指向它的变量名信息——一个对象可以被多个变量引用,甚至没有名字(比如匿名对象mytest())。所以没法直接从内存地址反向“查”到变量名,只能通过遍历命名空间里的引用关系来匹配。
可行的解决方法
我们可以遍历目标作用域的命名空间字典(比如全局的globals()、局部的locals()),检查每个变量对应的对象ID是否和目标内存地址一致,从而找出对应的变量名。
示例代码
class mytest(): pass x = mytest() # 目标内存地址(可以是整数形式,或者十六进制转整数) target_address = 140696428216768 # 如果是十六进制字符串,先转成整数:target_address = int('0x7ff670a001c0', 16) def find_variable_names(target_addr): matched_names = [] # 遍历全局命名空间 for name, obj in globals().items(): if id(obj) == target_addr: matched_names.append(name) # 遍历当前局部命名空间(如果在函数内部,局部命名空间会不同) for name, obj in locals().items(): if id(obj) == target_addr and name not in matched_names: matched_names.append(name) return matched_names # 调用函数 print(find_variable_names(target_address)) # 输出: ['x']
扩展说明
- 多作用域场景:如果对象是在函数内部、类的属性里,需要遍历对应作用域的字典。比如遍历类的
__dict__,或者函数内部的locals()。 - 多变量引用同一对象:如果多个变量指向同一个对象,这个方法会返回所有匹配的变量名。
- 注意事项:CPython实现下,
id()返回的整数就是对象的内存地址,所以直接用id(obj)和目标地址对比即可;另外,ctypes.cast的参数必须是整数类型的地址,传字符串会直接触发段错误,这也是你之前操作失败的原因。
内容的提问来源于stack exchange,提问作者showkey




