Python Twisted: 等待另一个事件填充变量

4 投票
1 回答
1455 浏览
提问于 2025-04-16 03:40

我知道 twisted 不会“等待”... 我正在使用一个 XMPP 客户端与外部程序交换数据。我发送一个请求,需要获取相应的答案。我用 sendMessage 方法把请求发送到服务器。当服务器回复时,一个 onMessage 方法会接收到这个回复,并检查它是否是某个请求的答案(不一定是我想要的那个),然后把任何答案放进一个堆栈里。
在我发送请求后,我想把结果返回,所以我想从堆栈中取出我请求的响应并返回。
我读过关于线程、延迟、回调和条件的内容,尝试了很多例子,但都没有成功。所以我这里的示例代码是非常简化的伪代码,用来说明我的问题。任何建议都非常感谢。

class Foo(FooMessageProtocol):
    def __init__(self, *args, **kwargs):
        self.response_stack = dict()
        super(Foo, self).__init__(*args, **kwargs)    


    def sendRequest(self, data):
        self.sendMessage(id, data)
        # I know that this doesn't work, just to illustrate what I would like to do:
        while 1: 
            if self.response_stack.has_key(id):
               break
               return self.response_stack.pop(id) 


    def receiveAnswers(self, msg):
        response = parse(msg)
        self.response_stack[response['id']] = response

1 个回答

3

你不能直接把结果返回给 sendRequest,因为 sendRequest 不能等待结果。你需要让 sendRequest 返回一个 Deferred 对象,并在结果到达时触发它。

这样,调用 sendRequest 的代码就可以简单地给这个 deferred 添加一个回调函数,当有响应时就会调用这个回调。

类似这样的(伪代码):

class Foo(FooMessageProtocol):
    def __init__(self, *args, **kwargs):
        self._deferreds = {}
        super(Foo, self).__init__(*args, **kwargs)    

    def sendRequest(self, data):
        self.sendMessage(id, data)
        d = self._deferreds[id] = defer.Deferred()
        return d

    def receiveAnswers(self, msg):
        response = parse(msg)
        id = response['id']
        if id in self._deferreds:
            self._deferreds.pop(id).callback(response)

撰写回答