Python 如何从内存地址加载 Python 对象
python 如何从内存地址上加载 pythn 对象
在 python 中我们可以通过 id 函数来获取某个 python 对象的内存地址,或者可以通过调用对象的__repr__魔术函数来获取对象的详细信息
def tt():
print(111)
print(tt.__repr__())
print(id(tt))
但是不知大家是否想过,其实这个内存地址可以直接加载 python 对象的。有两种方法:
1. PyObj_FromPtr
在_ctypes 包中,就提供 PyObj_FromPtr 这个 api 去实现我们的需求。代码如下
def tt():
print(111)
print(tt.__repr__())
print(_ctypes.PyObj_FromPtr(id(tt)))
运行结果如下:
<function tt at 0x106c628c8>
<function tt at 0x106c628c8>
2. gc.get_objects
我们也可以通过 gc 的 get_objects 方法来实现。先来看一下官方介绍
gc.get_objects()
Returns a list of all objects tracked by the collector, excluding the list returned.
大致意思为,获取所有可以追踪的对象。所以,我们可以通过第二种方式来实现从特定内存地址加载 python 对象
def tt():
print(111)
print(tt.__repr__())
for i in gc.get_objects():
if id(i) == id(tt):
print(i)
方法很简单,通过 gc.get_objects 获取所有对象,一一检查这些对象的内存地址是否与给定的内存地址相符,如果相符则返回对象。
结论
额,很扯淡的东西,最好不要乱用这种东西。因为出错的话,try except 语句都无法捕捉到这种异常。就当是了解一下吧
Python 如何从内存地址加载 Python 对象
1 回复
import ctypes
# 方法1:使用ctypes直接读取内存地址
def load_object_from_address(address):
"""
从内存地址加载Python对象
address: 整数形式的内存地址(如 id(obj) 返回的值)
返回:对应的Python对象
"""
# 将地址转换为ctypes指针
obj_ptr = ctypes.cast(address, ctypes.py_object)
# 获取指针指向的对象
return obj_ptr.value
# 方法2:更安全的版本,带类型检查
def safe_load_from_address(address, expected_type=None):
"""
安全地从内存地址加载对象,可指定期望类型
address: 内存地址
expected_type: 期望的对象类型(可选)
"""
try:
obj = load_object_from_address(address)
if expected_type and not isinstance(obj, expected_type):
raise TypeError(f"对象类型为 {type(obj)},不是期望的 {expected_type}")
return obj
except Exception as e:
raise ValueError(f"无法从地址 {address} 加载对象: {e}")
# 使用示例
if __name__ == "__main__":
# 创建一个测试对象
test_list = [1, 2, 3, "hello"]
# 获取对象的内存地址
address = id(test_list)
print(f"对象内存地址: {address} (0x{address:x})")
# 从地址重新加载对象
reloaded_list = load_object_from_address(address)
print(f"重新加载的对象: {reloaded_list}")
print(f"是同一个对象吗?: {reloaded_list is test_list}")
# 修改原始对象
test_list.append("world")
print(f"修改后重新加载的对象: {reloaded_list}")
# 安全加载示例
try:
safe_obj = safe_load_from_address(address, list)
print(f"安全加载成功: {safe_obj}")
except Exception as e:
print(f"安全加载失败: {e}")
# 重要说明:
# 1. 这种方法只适用于当前Python进程中的对象
# 2. 如果对象已被垃圾回收,访问地址会导致段错误或未定义行为
# 3. 主要用于调试和特殊场景,日常编程中应避免使用
核心就两点:用ctypes.cast把地址转成指针,再用.value取对象。这玩意儿一般只在调试内存问题时用用,正常写代码别这么搞。

