为什么sys.getsizeof()不在Python的file.read([size])中返回[size]?

0 投票
2 回答
626 浏览
提问于 2025-04-30 22:15

我有一个很大的二进制文件,想用struct.unpack()来读取和解压这个文件。这个文件由很多行组成,每行长2957个字节。我用下面的代码来读取这个文件:

with open("bin_file", "rb") as f:
    line = f.read(2957)

我想问的是,为什么下面这个返回的大小:

import sys
sys.getsizeof(line)

和2957不一样(在我的情况下是2978)?

暂无标签

2 个回答

3

一个表示2957字节数据的字符串对象,实际上占用的内存会超过2957字节。这是因为在存储这个字符串时,还需要额外的空间来保存一些信息,比如类型指针和引用计数。sys.getsizeof这个函数会把这些额外的内存也算在内。

7

你误解了 sys.getsizeof() 的作用。它返回的是 Python 用于一个字符串对象的内存大小,而不是字符串的长度。

Python 的字符串对象会记录引用计数、对象类型和其他一些信息,连同实际的字符一起存储,所以 2978 字节并不等于字符串的长度。

你可以查看 stringobject.h 中对这个类型的定义

typedef struct {
    PyObject_VAR_HEAD
    long ob_shash;
    int ob_sstate;
    char ob_sval[1];

    /* Invariants:
     *     ob_sval contains space for 'ob_size+1' elements.
     *     ob_sval[ob_size] == 0.
     *     ob_shash is the hash of the string or -1 if not computed yet.
     *     ob_sstate != 0 iff the string object is in stringobject.c's
     *       'interned' dictionary; in this case the two references
     *       from 'interned' to this object are *not counted* in ob_refcnt.
     */
} PyStringObject;

其中 PyObject_VAR_HEADobject.h 中定义,标准的 ob_refcntob_typeob_size 字段都在这里。

所以,一个长度为 2957 的字符串占用 2958 字节(字符串长度 + 结束符),而你看到的剩下的 20 字节是用来存储引用计数、类型指针、对象的“大小”(这里是字符串长度)、缓存的字符串哈希值和内部状态标志。

其他类型的对象会占用不同的内存空间,而且不同平台上使用的 C 类型的具体大小也会有所不同。

撰写回答