【问题标题】:Refactoring for a twisted tcp client from existing blocking code从现有阻塞代码重构扭曲的 tcp 客户端
【发布时间】:2013-11-28 19:09:50
【问题描述】:

我有一个 python 程序,它当前使用我编写的 tcp/ip 客户端模块从流服务器接收数据。服务器输出数据行。

我的 TCP 客户端类相当原始,我想重构以使用扭曲的 ReconnectingClientFactory。

主程序当前从我的 TCP 客户端中的 readLines 函数获取数据,该函数在收到行时“生成”行。

TCP客户端方法被访问:

for msg_buffer in self.myTcpClient.readLines():
    do some stuff with the data in msg_buffer

在我的 TCP 客户端中,readLines 方法本质上是这样的:

while True:
    newLine = self.sock.recv(self.buffer_size)
    yield newLine

当我实现扭曲的客户端时,我需要某种方式让它充当迭代器并产生数据。我假设我会在协议 dataReceived 方法中做一些事情。

我迷失了试图弄清楚这是如何工作的。在我看来,twisted deferred 是用于这种用途的,但我不知道如何将 deferred 用于我的目的(如果我对 deferred 的假设是正确的)。

在一个完美的世界中,扭曲的客户端会产生接收到的行,因此类似于当前方法的调用可以完成这项工作。即

class GetData(protocol):
    def dataReceived(self, data):
        yield data

但我认为这过于简单化了。

总之,我想做的是实现一个扭曲的重新连接 TCP 客户端,它的行为类似于我的 readLines 方法,并且可以或多或少地访问:

for msg_buffer in self.twistedTcpClient.readLines():

任何指针将不胜感激

更新: 我只是偶然发现了“钩针”的扭曲。乍一看,钩针编织似乎是专为我需要的那种模型而设计的……我会在一些测试后回来报告

【问题讨论】:

  • 如果您可以使您的帖子主题更能描述您遇到的问题,您将更有可能获得反馈。
  • 感谢 ASGM - 我更新了主题并添加了注释:钩针编织
  • 如果您可以包含一个完整的、可运行的程序而不仅仅是 sn-ps,那也会很有帮助。如果不查看完整的集成程序,很难 100% 确定您的要求。请参阅sscce.org 了解更多信息。
  • 最后我进行了重构,使程序的其余部分与 Twisted 的事件驱动性质兼容,这并没有我想象的那么困难。感谢您的帮助。

标签: python python-2.7 twisted twisted.internet twisted.client


【解决方案1】:

Twisted 的做法是编写一个协议。而不是这样做:

for line in self.twistedTcpClient.readLines():
    process_line(line) ...

你会编写你的协议(也许通过继承twisted.protocols.basic.LineReceiver):

class MyProtocol(LineReceiver):
    ...
    def lineReceived(self, line):
        process_line(line) ...

您想重构代码以使用 lineReceived 回调而不是迭代循环。

你写的:

for line in self.twistedTcpClient.readLines():
    process_line(line) ...

是有问题的,因为 Twisted 是异步的。在等待twistedTcpClient.readLines() 方法时,Twisted 没有办法做任何其他事情。

我建议写一个协议,但如果你真的坚持要有这种迭代器模式,那么你也许可以这样做:

@inlineCallbacks
def my_func():
    while True:
        try:
            line = yield self.twistedTcpClient.getNextLine()
        except StopIteration:
            break

        process_line(line) ...

现在,棘手的事情是让twistedTcpClient 在每次调用getNextLine() 时返回Deferreds。也许是这样的:

class MyProtocol(LineReceiver):
    ...
    def getNextLine(self):
        self.defer_given_out = Deferred()

    def lineReceived(self, line):
        self.defer_given_out.callback(line)

    def connectionLost(self):
        self.defer_given_out.errback(StopIteration())

(这只是一个说明这个想法的例子,你必须扩展它来处理细节。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多