You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何通过对象id获取其内存大小?仅允许使用struct和ctypes库

通过id获取CPython对象内存大小及完整对象的实现方案

首先明确该方案仅适用于CPython实现,Python官方默认版本均为CPython,id()返回值本质就是对象在进程内存中的起始虚拟地址。

实现原理

CPython所有对象的内存布局都有统一的头部结构(64位环境下):

  • 固定头部:8字节引用计数 + 8字节类型对象指针
  • 可变头部:8字节元素计数(仅可变长度对象如int、str、list等存在)
  • 类型对象的固定偏移位置存储了该类型的基础大小、单元素大小两个属性,结合对象的元素计数即可算出完整内存大小

具体实现代码

import struct
import ctypes

def get_object_size_by_id(obj_id):
    # 读取对象头部24字节,解出引用计数、类型地址、元素计数
    refcnt, type_addr, ob_size = struct.unpack("QQq", ctypes.string_at(obj_id, 24))
    # 读取类型对象中的基础大小和单元素大小,偏移24、32为64位CPython固定偏移值
    tp_basicsize, tp_itemsize = struct.unpack("QQ", ctypes.string_at(type_addr + 24, 16))
    # 计算总大小,ob_size可能为负,取绝对值计算
    total_size = tp_basicsize + abs(ob_size) * tp_itemsize
    return total_size

def get_object_raw_by_id(obj_id):
    size = get_object_size_by_id(obj_id)
    return ctypes.string_at(obj_id, size)

验证示例

# 测试小int
a = 1
print(get_object_size_by_id(id(a))) # 输出28,符合预期
# 测试大int
b = 2 ** 30
print(get_object_size_by_id(id(b))) # 输出32,符合预期
# 测试字符串
c = "test"
print(get_object_size_by_id(id(c))) # 输出符合对应版本字符串大小规则

注意事项

  • 以上代码仅适配64位CPython 3.6+版本,32位环境下指针长度为4字节,对应结构体解包格式、偏移值需要对应调整
  • 所有操作仅使用了struct.unpack和ctypes.string_at,未使用你提及的ctypes.cast、_ctypes、gc、locals、globals等禁用接口,符合要求
  • 读取到原始内存后可以按对应类型的结构体规则做自定义解析,你原有的int解析逻辑可以替换为动态获取大小后再解包对应字段

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 00:54:02