gpt4 book ai didi

python - 从 ctypes.Union 派生的 Monkey Patching 类不起作用

转载 作者:太空宇宙 更新时间:2023-11-04 04:25:40 24 4
gpt4 key购买 nike

我正在尝试“猴子修补”一个派生自 Python ctypes“Union”的类,但我无法这样做 - 出现奇怪的错误,有时还会出现段错误。当从 ctypes“结构”派生时,同样的事情工作得很好。

我已将其缩小到我在下面发布的最简单的测试用例。我正在使用 Python 3.6.4。我想知道我是否做错了什么(或者 ctypes“Union”实现有问题吗?)。请查看下面的代码和相应的输出。

import ctypes

def display(self):
""" A new kind of display """
return f'Print Type #2: ( {self.y1}, {self.y2} )'

class MyStruct(ctypes.Structure):
_fields_ = [
('y1', ctypes.c_uint32),
('y2', ctypes.c_uint32)
]

def __str__(self):
return f'Print Type #1: [ {self.y1}, {self.y2} ]'

class MyUnion(ctypes.Union):
_fields_ = [
('y1', ctypes.c_uint32),
('y2', ctypes.c_uint32)
]

def __str__(self):
return f'Print Type #1: [ {self.y1}, {self.y2} ]'

if __name__ == '__main__':

a = MyStruct()
a.y1 = 10
a.y2 = 20

print('Using Structure:')
print('----------------')
print(a)
print('Original :', MyStruct.__str__)
# monkey patch __str__ with a different function.
MyStruct.__str__ = display
print('Patched :', MyStruct.__str__)
print('Patched (dict) :', MyStruct.__dict__['__str__'])
print(a)

a = MyUnion()
a.y1 = 10
a.y2 = 20

print('Using Union:')
print('------------')
print(a)
print('Original :', MyUnion.__str__)
# monkey patch __str__ with a different function.
MyUnion.__str__ = display
print('Patched :', MyUnion.__str__)
print('Patched (dict) :', MyUnion.__dict__['__str__'])
print(a)

这是我运行程序时的输出。

Using Structure:
----------------
Print Type #1: [ 10, 20 ]
Original : <function MyStruct.__str__ at 0x7fdf89d02e18>
Patched : <function display at 0x7fdf8b0ebe18>
Patched (dict) : <function display at 0x7fdf8b0ebe18>
Print Type #2: ( 10, 20 )
Using Union:
------------
Print Type #1: [ 20, 20 ]
Original : <function MyUnion.__str__ at 0x7fdf89d02f28>
Patched : <function MyUnion.__str__ at 0x7fdf89d02f28>
Patched (dict) : <function display at 0x7fdf8b0ebe18>
Traceback (most recent call last):
File "ctypes_bug.py", line 54, in <module>
print(a)
TypeError: 'managedbuffer' object is not callable

显然,当相应的 Python 对象派生自“Structure”时,我能够“修补”__str__,但当相应的 Python 对象派生自“Union”。

有趣的是,MyUnion.__dict__[__str__]MyUnion.__str__ 显示不同的结果——这也很奇怪。

我这里有什么地方做错了吗?我非常感谢任何帮助或见解!

最佳答案

我认为这里确实存在 CPython 错误。 __setattr__ implementation对于结构类型的类型对象,使用 PyType_Type.tp_setattro:

static int
PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value)
{
/* XXX Should we disallow deleting _fields_? */
if (-1 == PyType_Type.tp_setattro(self, key, value))
return -1;

if (value && PyUnicode_Check(key) &&
_PyUnicode_EqualToASCIIString(key, "_fields_"))
return PyCStructUnionType_update_stgdict(self, value, 1);
return 0;
}

但是the one for type objects for union types使用 PyObject_GenericSetAttr:

static int
UnionType_setattro(PyObject *self, PyObject *key, PyObject *value)
{
/* XXX Should we disallow deleting _fields_? */
if (-1 == PyObject_GenericSetAttr(self, key, value))
return -1;

if (PyUnicode_Check(key) &&
_PyUnicode_EqualToASCIIString(key, "_fields_"))
return PyCStructUnionType_update_stgdict(self, value, 0);
return 0;
}

必须使用 PyType_Type.tp_setattro 来更新类型槽并使 internal type attribute cache 无效. PyObject_GenericSetAttr 不知道它应该做这些事情中的任何一个,从而导致由于“僵尸”缓存属性而导致潜在的内存损坏。看起来同样的错误是 fixed 2008 年初的结构,但他们忘记处理联合。

关于python - 从 ctypes.Union 派生的 Monkey Patching 类不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53563561/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com