gpt4 book ai didi

python - 在扭曲中顺序排队多个延迟

转载 作者:太空狗 更新时间:2023-10-30 02:21:31 25 4
gpt4 key购买 nike

目前我还是twisted的初学者,这让我很烦恼。

我正在通过 TCP 发送一系列命令并等待来自 lineRecieved 阅读器的响应,这可能需要几秒钟的时间来处理和到达,所以我将它包装在一个 defered 中。第一个延迟工作正常,但第二个延迟触发,因为第一个延迟仍在处理中导致垃圾,因为端点一次只能处理一个命令。 asysc 系统中的预期行为,但不是我需要发生的行为。如果我有一个或两个命令,我可以使用 deferedChain 来处理,但由于我可能有几十个命令要按顺序运行,我担心这会很快变成无法维护的意大利面条。

执行此操作的简洁方法是什么?

非常感谢

示例代码

def connectionMade(self):
self.fire_def('command1')
print'fire command 2'
self.fire_def('command2')#Fires when command one is running

def fire_def(self,request):
d = self.getInfo(request)
d.addCallback(self.print_result)
return d

def print_result(result):
print result


def getInfo(self,request):
print 'sending', request
self.d = defer.Deferred()
self.sendLine(request)
return self.d

def lineReceived(self, line):
line = line.strip()
self.buffer.append(line)
if self.d is None:
return
if 'result_I_want' in self.buffer:
print 'Firing Callback'
self.d.callback(self.buffer)

最佳答案

您问题中的代码只知道如何跟踪一个Deferred。如果应用程序代码调用 getInfo 两次而没有足够的干预时间来完成第一个操作并获得结果,那么它将破坏其自身的内部跟踪状态:

def getInfo(self,request):
print 'sending', request
self.d = defer.Deferred()
self.sendLine(request)
return self.d

d_foo = getInfo(foo)
d_bar = getInfo(bar)

在这个序列中,d_food_bar 是不同的Deferred 实例。但是,在第二次调用 getInfo 时,self.d 属性的值从 d_foo 更改为 d_bard_foo Deferred 丢失了。稍后,当 `lineReceived 运行时:

def lineReceived(self, line):
line = line.strip()
self.buffer.append(line)
if self.d is None:
return
if 'result_I_want' in self.buffer:
print 'Firing Callback'
self.d.callback(self.buffer)

self.dd_bar,即使该行可能是对 foo 请求的响应。这意味着 d_bar 将获得 foo 的响应,而 d_foo 将永远不会获得任何响应。

要解决此问题,在协议(protocol)上保留一个 Deferred 实例列表(或队列)可能会有所帮助。当发出新的信息请求时附加到它,当收到响应时从它的前面弹出。 (我不确定你正在实现什么协议(protocol),所以我不知道你将如何决定多少行足以构成一个响应。如果协议(protocol)没有定义它那么它就被破坏了,你可能想要切换到更好的协议(protocol)。)

如果您修复此问题,那么响应至少会传送到不同的 Deferred 实例。

您还描述了与强制顺序操作相关的问题。我可以通过几种方式来解释这一点。一种方法是将其解释为您一次只希望一个请求在网络上“未完成”。换句话说,您不希望 getInfo 发送 新的请求行,直到 lineReceived 将响应数据传递给 Deferred上一个 调用 getInfo 返回。

在这种情况下,延迟链接就可以了。尽管您有 N 个 Deferred,但当您施加此顺序限制时,您实际上有一系列 2 个 Deferred。您有更早运行的 Deferred 和只应在较早的结果产生结果后才运行的 Deferred。您将此扩展到 N,然后将较晚的 Deferred 视为新对中较早的 Deferred,并且第三个 Deferred 成为新的较晚的 Deferred。

或者换句话说,如果你有 D1、D2、D3 和 D4,那么你可以像这样链接它们:

D2 is chained to D1 and only runs when D1 is complete
D3 is chained to D2 and only runs when D2 is complete
D4 is chained to D3 and only runs when D3 is complete

然而,虽然这可行,但它实际上并不是实现序列化的最简单方法。相反,我建议在 getInfo 中显式排队工作,并在 lineReceived: 中显式取消排队。

def _sendRequest(self, d, request):
print 'sending', request
self.d = d
self.sendLine(request)

def getInfo(self,request):
if self.d is None:
d = defer.Deferred()
self._sendRequest(d, request)
return d
else:
queued_d = defer.Deferred()
self._requests.append((request, queued_d))
return queued_d


def lineReceived(self, line):
line = line.strip()
self.buffer.append(line)
if self.d is None:
return
if 'result_I_want' in self.buffer:
print 'Firing Callback'
now_d = self.d
self.d = None
buffer = self.buffer
self.buffer = []
if self._requests:
request, queued_d = self._requests.pop(0)
self._sendRequest(queued_d, request)
now_d.callback(buffer)

请注意 lineReceived 中的代码如何在 now_d.callback(buffer) 行之前注意将所有内容置于一致状态。这是一个微妙但重要的观点。 now_d 上可能存在影响协议(protocol)的回调 - 例如,再次调用 getInfo。在导致该代码运行之前,协议(protocol)处于一致状态很重要,否则它会变得困惑 - 可能通过乱序发送请求,或者在实际应该发送请求时排队请求。这是使代码安全以防止重入 的示例。这并不是使用 Twisted 的程序独有的想法,但由于人们最常将重入的想法与线程程序联系在一起,因此人们在编写基于 Twisted 的代码时常常忽略这种可能性。

关于python - 在扭曲中顺序排队多个延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15620978/

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