You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从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']

扩展说明

  1. 多作用域场景:如果对象是在函数内部、类的属性里,需要遍历对应作用域的字典。比如遍历类的__dict__,或者函数内部的locals()
  2. 多变量引用同一对象:如果多个变量指向同一个对象,这个方法会返回所有匹配的变量名。
  3. 注意事项:CPython实现下,id()返回的整数就是对象的内存地址,所以直接用id(obj)和目标地址对比即可;另外,ctypes.cast的参数必须是整数类型的地址,传字符串会直接触发段错误,这也是你之前操作失败的原因。

内容的提问来源于stack exchange,提问作者showkey

火山引擎 最新活动