Avete un paio di opzioni diverse, a seconda del tipo di loop principale del vostro programma esistente.
Se è un mainloop da una libreria della GUI, Twisted may already have support for it. In tal caso, puoi semplicemente andare avanti e usarlo.
Si potrebbe anche scrivere il proprio reattore. Non c'è molta documentazione per questo, ma you can look at the way that qtreactor implementa esternamente un plugin per reattore a Twisted.
È anche possibile scrivere un reattore minimo utilizzando threadedselectreactor
. Anche la documentazione per questo è scarsa, ma lo si utilizza con lo the wxpython reactor. Personalmente non consiglierei questo approccio in quanto è difficile da testare e potrebbe generare condizioni di gara confuse, ma ha il vantaggio di farvi sfruttare quasi tutto il codice di rete di Twisted con solo un sottile strato di wrapping.
Se siete veramente sicuri che non si desidera che il doComputation
di essere asincrona, e si desidera che il programma per bloccare durante l'attesa per Twisted rispondere, effettuare le seguenti operazioni:
- inizio ritorto in un altro thread prima che il tuo ciclo principale si avvii, con qualcosa come
twistedThread = Thread(target=reactor.run); twistedThread.start()
- istanzia un oggetto per fare la tua comunicazione RPC (diciamo,
RPCDoer
) nel thread del tuo ciclo principale, in modo da avere un riferimento ad esso. Assicurati di dare il via alla logica Twisted con reactor.callFromThread
in modo da non dover includere tutte le sue chiamate API Twisted.
- Implementare
RPCDoer.doRPC
per restituire un Deferred, utilizzando solo le chiamate Twisted API (ovvero non chiamare nel codice dell'applicazione esistente, quindi non è necessario preoccuparsi della sicurezza del thread per gli oggetti dell'applicazione, passare doRPC
tutte le informazioni che esso bisogni come argomenti).
È ora possibile implementare doComputation
così:
def doComputation(self):
rpcResult = blockingCallFromThread(reactor, self.myRPCDoer.doRPC)
return self.computeSomethingFrom(rpcResult)
- ricordarsi di chiamare
reactor.callFromThread(reactor.stop); twistedThread.join()
dalla procedura di arresto il vostro principale del circuito, altrimenti si rischia di vedere alcuni traceback confuse o registrare i messaggi in uscita.
Infine, un'opzione da prendere in considerazione, soprattutto a lungo termine: scaricare il loop principale esistente e individuare un modo per utilizzare semplicemente Twisted. Nella mia esperienza questa è la risposta giusta per 9 su 10 di domande come questa. Non sto dicendo che questo è sempre la strada da percorrere - ci sono molti casi in cui hai davvero bisogno di mantenere il tuo ciclo principale, o dove è solo troppo sforzo per sbarazzarsi del ciclo esistente.Ma mantenere il tuo loop è anche un lavoro. Tieni presente che il loop Twisted è stato ampiamente testato da milioni di utenti e utilizzato in una grande varietà di ambienti. Se il tuo ciclo è anche estremamente maturo, potrebbe non essere un grosso problema, ma se stai scrivendo un piccolo, nuovo programma, la differenza di affidabilità potrebbe essere significativa.
grazie per la grande risposta! Sto appoggiando il secondo al penultimo approccio, ma penso di sostituire il mio ciclo principale. ora, c'è un vantaggio nell'esecuzione ritorta in un thread separato rispetto a eseguirlo come thread principale e chiamando il mio ciclo principale con 'reactor.callInThread()'? – Claudiu
blockingcallfromtrhead è la strada da percorrere – Claudiu