打印CPython对象的底层C结构表示

2024-09-29 01:37:43 发布

您现在位置:Python中文网/ 问答频道 /正文

在这种情况下,任何Python对象都实现为带有一些字段的C结构。包含引用计数和指向对象类型的指针的16字节header始终存在于该结构上。这至少是64位股票cpython3.x的情况,我的问题是有限的。你知道吗

出于学术目的和乐趣,我正在搜索一个函数print_object(obj),它打印出传递对象obj的底层struct。你知道吗

就实现而言,最简单的Python对象可能是float,它只是附加到前面提到的头的一个C double。在这个简单的例子中,我可以使用ctypesstruct模块编写自己的函数:

import collections, ctypes, struct, sys

header_fields = ['refcount', 'typeptr']
Float = collections.namedtuple('Float', header_fields + ['value'])

def print_object(obj):
    ptr = id(obj)
    size = sys.getsizeof(obj)
    byterep = ctypes.string_at(ptr, size)
    header = struct.unpack('qq', byterep[:16])
    if isinstance(obj, float):
        obj_struct = Float(*header, *struct.unpack('d', byterep[16:]))
    elif isinstance(obj, int):
        ...
    print(obj_struct)

# Try it out
a = 1.23
print_object(a)
print('The typeptr should be equal to', id(float))
print('\nNow the refcount should have increased by 1:')
b = a
print_object(a)

本质上,这个函数读取对象的底层内存,并将C struct的副本构建为Python namedtuple,有效地重新表示Python本身。代码应该在python3.5及更高版本上运行。它打印出来了

Float(refcount=5, typeptr=140429307606720, value=1.23)
The typeptr should be equal to 140429307606720

Now the refcount should have increased by 1:
Float(refcount=6, typeptr=140429307606720, value=1.23)

上面的print_object函数对float非常有用,同样的方法可以扩展到(我想是吧?)所有其他类型。有没有任何库(甚至Python标准库)包含这样的功能?你知道吗


Tags: 对象函数objobjectvaluefloatctypesstruct
1条回答
网友
1楼 · 发布于 2024-09-29 01:37:43

尝试自动执行此操作的问题是,没有通用的方法来获取Python类型的布局。见鬼,甚至没有一个通用的方法来判断这个结构有多大。另外,使用class语句创建的类型并不完全使用struct作为其实例,尽管它们的工作方式大多类似于结构。你知道吗

您需要自己为任何想要使用的类型提供结构定义,并且仍然需要对具有特别奇怪表示的intstr等类型进行自定义处理。你知道吗

相关问题 更多 >