Rifactoring per un client TCP contorto dal codice di blocco esistente
-
20-12-2019 - |
Domanda
Ho un programma Python che attualmente utilizza un modulo client TCP / IP che ho scritto per ricevere dati da un server di streaming. Il server emette linee di dati.
La mia classe client TCP è abbastanza primitiva e voglio refactor per utilizzare una riconnectClittyClient intrecciata.
Il programma principale ottiene attualmente i dati da una funzione di readlines nel mio client TCP che "produce" le linee come vengono ricevute.
Il metodo client TCP è accessibile da:
for msg_buffer in self.myTcpClient.readLines():
do some stuff with the data in msg_buffer
.
Nel mio client TCP il metodo Readlines in Essence sembra:
while True:
newLine = self.sock.recv(self.buffer_size)
yield newLine
.
Quando implemendo il client contorto, voglio qualche modo per comportarsi come un iteratore e fornire dati. Presumo che avrei fatto qualcosa nel metodo DataRecito del protocollo.
Ho perso il tentativo di capire come funziona. Mi sembra che è tortolato differito è pensato per questo tipo di utilizzo, ma non riesco a capire come usare un differitore per il mio scopo (se la mia ipotesi di differita è corretta).
In un mondo perfetto il cliente contorto produrrebbe le linee come ricevute, quindi una chiamata simile al presente metodo farebbe il lavoro. I.e.
class GetData(protocol):
def dataReceived(self, data):
yield data
.
Ma penso che sia una semplificazione eccessiva.
In sintesi, quello che sto cercando di fare è implementare un client TCP di riconnessione contorto che si comporta come il mio metodo di readlines e può essere accessibile più o meno come:
for msg_buffer in self.twistedTcpClient.readLines():
.
Qualsiasi puntatori sarà molto apprezzato
Aggiornamento: Ho appena inciampato attraverso "uncinetto" per contorto. A Prima occhiata all'uncinetto sembra essere stato progettato per esattamente il tipo di modello che ho bisogno ... riporterò indietro dopo alcuni test
Soluzione
Il modo intrecciato di fare questo sarebbe quello di scrivere un protocollo.Invece di fare:
for line in self.twistedTcpClient.readLines():
process_line(line) ...
.
Scrivi il tuo protocollo (forse controclassazione di un twisted.protocols.basic.LineReceiver
):
class MyProtocol(LineReceiver):
...
def lineReceived(self, line):
process_line(line) ...
.
Si desidera refatturare il tuo codice per utilizzare la richiamata lineReceived
, anziché avere un loop iterate.
Cosa hai scritto:
for line in self.twistedTcpClient.readLines():
process_line(line) ...
.
è problematico come intrecciato è asincrono.Non c'è modo di torto a spostarsi per fare nient'altro mentre aspetti il metodo twistedTcpClient.readLines()
.
Suggerisco di scrivere un protocollo, ma se hai davvero insistito su Avere questo motivo Iteratore, potresti essere in grado di farlo:
@inlineCallbacks
def my_func():
while True:
try:
line = yield self.twistedTcpClient.getNextLine()
except StopIteration:
break
process_line(line) ...
.
Ora, la cosa complicata è rendere twistedTcpClient
Return Deferreds
per ogni chiamata a GetNextline ().Forse qualcosa del genere:
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())
.
(Questo è solo un esempio che illustra l'idea, dovresti estenderlo per gestire i dettagli.)