python - Twisted Matrix Callback call again and again -
i need when user click button, button fire callback , pass parameters, each time, parameters different.
i've looked @ documentation appear part looping missing:
looping common form of dependency needing perform asynchronous operation on again. canonical example of http redirect: when callback deferred page request returned, result, or empty body location http header set, in case perform operation on again. [ here http redirect example. should have pictures. ]
the if working, try also, callback run once
if happen this: try: print "i'm here!" myobjectx.addcallback(test,x,y,z) myobjectx.callback() except: ...
just idea of how work:
1) create myobject nothing 2) when event fired prepare callback myobject e execute 3) how can redo callback next time event happen again?
i'm looking @ pymodbus library example of async client:
https://pymodbus.readthedocs.org/en/latest/examples/asynchronous-client.html
i've got 2 files:
mainprocess modbuslib
from mainprocess call
myobjectx = modbuslib.protocol.clientcreator(reactor, modbusclientprotocol ).connecttcp("localhost", defaults.port)
then in function triggered if:
if ('gigiisclicked' in existkeys): myobjectx.addcallback(beginasynchronoustest) myobjectx.callback(beginasynchronoustest) print "executed"
and is, print repeated again , again when event occours callback no.
i think 1 misunderstanding here how instances of deferred
meant used.
you should think of deferred
having 2 different kinds of (albeit highly related) uses.
one use able publish event code knows how notice events have happened other code might interested know event has happened.
one example of use clientcreator.connecttcp
: implementation of api knows when tcp connection attempt has succeeded (or failed) , uses deferred
publish information other code. code using deferred
code instantiates deferred
(eg, d = deferred()
) , later uses deferred.callback
, deferred.errback
.
the other use of deferred
allow code interested in events has happened learn events have happened. example, application wants tcp connection in order exchange data - needs wait while 1 being set before can proceed. code using deferred
code uses deferred.addcallback
or deferred.adderrback
(also, deferred.cancel
in recent versions of twisted).
deferred.addcallback
api use specify code run when deferred
gets result.
deferred.callback
api use supply result deferred
. and, importantly, deferred
can ever given 1 result. each deferred
instance represents completion of single operation or occurrence of single event.
there exceptions , further subtleties rule of thumb if code didn't instantiate deferred
code should not use callback
(or errback
) methods. calling 1 of job whatever code created deferred
.
given that, hope it's clear use of deferred
apis in code has problems need addressed:
myobjectx = modbuslib.protocol.clientcreator(reactor, modbusclientprotocol ).connecttcp("localhost", defaults.port) ... if ('gigiisclicked' in existkeys): myobjectx.addcallback(beginasynchronoustest) myobjectx.callback(beginasynchronoustest) print "executed"
most directly, shouldn't calling myobjectx.callback
here. that's clientcreator.connecttcp
's job (on top of that, beginasynchronoustest
doesn't make sense result deferred
have).
instead, think want use methods of modbusclientprotocol
instance clientcreator.connecttcp
create you. in example linked to, notice beginasynchronoustest
defined accept 1 argument named client
.
since beginasynchronoustest
passed addcallback
method of deferred
returned clientcreator.connecttcp
means called instance of protocol clientcreator
initialized (in case, modbusclientprotocol
). beginasynchronoustest
called deferred
given result implementation of clientcreator
- in other words, called connection established. setting tcp connection takes arbitrary amount of time since involves exchanging data arbitrary other computers on arbitrary network links - there's no telling how long resources take complete part of connection setup.
once beginasynchronoustest
called have connection - represented modbusclientprotocol
instance passed in it. point in program might able start doing multiple things (for example, doing each time button clicked).
at point deferred
program started out (called myobjectx
in snippets of code above) done , no longer useful or interesting won't using anymore.
instead, you'll calling methods of modbusclientprotocol
(read_coils
or write_coil
or whatever else want do). each of these methods returns brand new deferred
representing result of particular operation. you'll want use addcallback
these in order learn results.
the other place people stumble figuring out how make these additional method calls. if you're adding code body of beginasynchronoustest
it's straightforward how this:
reading = client.read_coils(1, 1)
however, suspect won't want add button handling code body of beginasynchronoustest
. instead, have event handler somewhere else in program gets called time button has been pressed. fortunately, it's not more complicated deal situation.
the key remember time have reference connection you'll able use it. inside body of beginasynchronoustest
have reference - client
parameter. can make reference available other parts of program too: setting attribute on object shared necessary parts of program 1 common, way this.
class buttonmodbussomething(object): def __init__(self): self.client = none def connect(self): creator = modbuslib.protocol.clientcreator(reactor, modbusclientprotocol) connecting = creator.connecttcp("localhost", defaults.port) connecting.addcallback(self._connected) connecting.adderrback(log.err) def _connected(self, client): self.client = client def buttonclicked(self, existkeys): if self.client not none: if "gigiisclicked" in existkeys: self.client.read_coil(1, 1)
notice how client
attribute of buttonmodbussomething
starts off none
, how buttonclicked
needs check case. mentioned above, setting connection can take time , way know how long wait _connected
called. check ensures if button clicked before connection exists event ignored (you may want handle more nicely - example, starting user interface in disabled state , switching on when connection set up).
also, i've left out code want handle connection being lost. when happens, client
attribute no longer useful. still reference modbusclientprotocol
connected, since protocol instance no longer has connection it's hard useful with. want re-disable user interface when connection lost or @ least start ignoring button presses again.
also, notice clientcreator
comes twisted.internet.protocol
not modbuslib.protocol
.
Comments
Post a Comment