你如何看待这个Python错误?

2 投票
2 回答
3066 浏览
提问于 2025-04-15 13:47

这是错误信息。

Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 295, in 'calling callback function'
  File "USB2.py", line 454, in ff
    self.drv_locked = False
SystemError: Objects/cellobject.c:24: bad argument to internal function

这是相关的Python代码。

def drv_send(self, data, size):
    if not self.Connected():
        return

    def f():
        self.drv_locked = True
        buffer = ''.join(chr(c) for c in data[:size])
        out_buffer = cast(buffer, POINTER(c_uint8))
        request_handle = (OPENUSB_REQUEST_HANDLE * 1)()
        request = (OPENUSB_INTR_REQUEST * 1)()

        request_handle[0].dev = self.usbhandle
        request_handle[0].interface = INTERFACE_ID
        request_handle[0].endpoint = LIBUSB_ENDPOINT_OUT + 1
        request_handle[0].type = USB_TYPE_INTERRUPT
        request_handle[0].req.intr = request
        def f(req):
            print req[0].req.intr[0].result.status, req[0].req.intr[0].result.transferred_bytes
            self.drv_locked = False # Line 454
        request_handle[0].cb = REQUEST_CALLBACK(f)
        request_handle[0].arg = None

        request[0].payload = out_buffer
        request[0].length = size
        request[0].timeout = 5000
        request[0].flags = 0
        request[0].next = None

        r = lib.openusb_xfer_aio(request_handle)
        print "result", r

    self.command_queue.put(f)

还有这是相关的Python源代码。

PyObject *
PyCell_Get(PyObject *op)
{
        if (!PyCell_Check(op)) {
                PyErr_BadInternalCall(); // Line 24
                return NULL;
        }
        Py_XINCREF(((PyCellObject*)op)->ob_ref);
        return PyCell_GET(op);
}

2 个回答

2

PyCell_Check这个函数是用来检查它接收到的参数是否真的是一个“单元格”对象(这是一种内部类型,用来实现被多个作用域引用的变量)。如果op不是一个单元格对象,你就会看到这个错误。

你发的代码没有提供足够的上下文或信息,所以我们无法准确判断这个错误参数是怎么传递过来的。

6

内部错误显然是Python本身的一个bug。如果你想进一步研究这个问题,并为Python核心提供修复,那么简化你的代码到仍然能触发这个bug的程度就是一个正确的策略。

不过,如果你更关心的是让你的代码正常工作,而不是修复Python核心,那么我建议你避免代码中一些可能让Python感到困惑的异常情况。例如,我不知道有没有人测试过一个名为f的嵌套函数里面还有一个同样名为f的更深层嵌套函数——这应该是可以工作的,但正是这种情况可能没有经过充分测试,因为没人想到过。而故意制造这种异常情况是加强测试套件的一个很好策略,但如果你不是故意想要触发Python内部的bug,最好还是避免这样做。

所以,首先,我会确保没有同名的情况。如果这样仍然有bug,我接下来会通过将当前对非局部变量的访问转换为“预绑定参数”来去掉对单元对象的使用。例如,你的“半外部”f可以改成:

def f(self=self):

而你的“完全内部的”可以变成:

def g(req, self=self):

这样在这两个函数中对self的访问(当前是非局部变量的访问)就变成了局部变量的访问。是的,你本不应该这样做(任何软件都不应该有bug,让你需要绕过它们),但可惜的是,完美并不是这个世界的特性,所以学习如何处理bug的策略是生活中不可避免的一部分;-)。

撰写回答