既存のブロッキングコードからのツイストTCPクライアントのリファクタリング
-
20-12-2019 - |
質問
私は現在、ストリーミングサーバからデータを受信するために書き込んだTCP / IPクライアントモジュールを使用しているPythonプログラムを持っています。サーバーはデータの行を出力します。
My TCPクライアントクラスはかなりプリミティブであり、私はTwisted ReconnectionClientFactoryを使用することをリファクタリングしたいです。
メインプログラムは現在、私のTCPクライアントのReadlines関数からのデータを受信したときに '歩留まり'を取得します。
TCPクライアント方式にアクセスします。
for msg_buffer in self.myTcpClient.readLines():
do some stuff with the data in msg_buffer
.
私のTCPクライアントでは、本質のRead Linesメソッドは次のようになります。
while True:
newLine = self.sock.recv(self.buffer_size)
yield newLine
.
ツイストクライアントを実装するとき、私はそれがイテレータとして行動し、データを歩留させるための何らかの方法を望みます。私はプロトコルDatereceivedメソッドで何かをすると思います。
これがどのように機能するかを理解しようとしています。 Twisted Deferedがこの種の使用のためのものであることが私に現れますが、私の目的のために遅延を使う方法を理解することはできません(延期に関する私の仮定が正しい場合)。
完璧な世界では、ツイストクライアントは受信したように回線を生み出して、現在の方法と同様の通話がジョブを実行するでしょう。すなわち。
class GetData(protocol):
def dataReceived(self, data):
yield data
.
しかし、それが明確にされていると思います。
まとめて、私がやろうとしているのは、私の読み取り方法のようなものを振る舞い、多かれ少なかれアクセスできるツイスト再接続TCPクライアントを実装することです。
for msg_buffer in self.twistedTcpClient.readLines():
.
任意のポインタは非常に高く評価されます
更新: 私はただ「かぎ針編み」を撚ってつまずくだけです。一見の編み出しは、私が必要とするモデルの種類のように設計されているようです...テストの後に報告します
解決
これを行うというツイストの方法はプロトコルを書くことです。する代わりに:
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) ...
.
はねじれが非同期であるとは問題がある。twistedTcpClient.readLines()
メソッドを待っている間、他に何もするようにねじれにくくの方法はありません。
プロトコルを書くことを提案するが、このイテレータパターンを持っていることを本当に主張すると、これを行うことができるかもしれません:
@inlineCallbacks
def my_func():
while True:
try:
line = yield self.twistedTcpClient.getNextLine()
except StopIteration:
break
process_line(line) ...
.
今、トリッキーなことはGetNextLine()の呼び出しごとにtwistedTcpClient
を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())
.
(これは、アイデアを説明する例であり、詳細を処理するために拡張する必要があります。)