纠结的扭曲回调函数

1 投票
1 回答
611 浏览
提问于 2025-04-16 01:27

我正在做一个有点复杂的教程,目的是为了更好地学习Python,但我在这里遇到了一些困难。下面的doRead()函数是一个反应器的“回调”函数。我不太明白的是,except部分是怎么工作的。

我理解代码的方式是,如果bytes += self.sock.recv(1024)导致了阻塞,那么代码会进入接下来的部分:

if e.args[0] == errno.EWOULDBLOCK:
    break

然后它会继续执行以下内容:

if not bytes:
    print 'Task %d finished' % self.task_num
    return main.CONNECTION_DONE
else:
    msg = 'Task %d: got %d bytes of poetry from %s'
    print  msg % (self.task_num, len(bytes), self.format_addr())

对我来说棘手的地方是,如果它真的阻塞了,那么bytes变量就应该什么都没有,应该打印“finish”,但实际上并没有。或者至少应该打印类似“获得了0字节”的内容,但也没有。看起来像是当代码在recv调用时遇到阻塞,它完全跳过了上面的部分。有人能解释一下为什么会这样吗?

输出大概是这样的:

Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 10 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 10 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 3 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000

这是整个函数:

def doRead(self):
    bytes = ''

    while True:
        try:
            bytes += self.sock.recv(1024)
            if not bytes:
                break
        except socket.error, e: # I don't understand this part
            if e.args[0] == errno.EWOULDBLOCK:
                break
            return main.CONNECTION_LOST

    if not bytes:
        print 'Task %d finished' % self.task_num
        return main.CONNECTION_DONE
    else:
        msg = 'Task %d: got %d bytes of poetry from %s'
        print  msg % (self.task_num, len(bytes), self.format_addr())

    self.poem += bytes

整个模块的代码在这里: http://pastebin.com/bUnXgbCA

1 个回答

2

重点是,方法 doRead 只有在套接字“准备好读取”时才会被调用:要么它上面有一些数据,要么就是已经完成了(这时读取会返回 0)。所以,你的问题的解决方案不在 doRead 函数里面——而是在于在合适的时候调用它的那段代码。

这段代码都在 Twisted 的“反应器”里面,PoetrySocket 的实例在 __init__ 方法中通过反应器的 addReader 方法把自己添加进去。如果你想深入理解 Twisted 的机制,看来你来对地方了(当然,前提是要研究 Twisted 的源代码;-)。

撰写回答