[Twisted-Python] asynchronous python generator
exarkun at twistedmatrix.com
exarkun at twistedmatrix.com
Mon Jul 12 12:00:24 MDT 2010
On 04:43 pm, jeandaniel.browne at gmail.com wrote:
>Hello,
>
>I wrote a small client protocol which connects to a notification
>server. The client role is to connect, and then to print the
>notification which comes from the server until the server says "stop"
>(a netcat server do just fine, I use "nc -C -l 6789"). I would like
>the API for this client protocol to be compatible with the "for"
>python loop. Here is the client
>
>class Notif(basic.LineReceiver):
>
> def lineReceived(self, data):
> self.d.callback(data)
>
> def __iter__(self):
> return self
>
> @defer.inlineCallbacks
> def next(self):
> self.d = defer.Deferred()
> notif = yield self.d
> if notif=="stop":
> defer.returnValue(Failure(StopIteration()))
> else:
> defer.returnValue(notif)
>
>Here is an example of how to use this client:
>
>
>@defer.inlineCallbacks
>def gotConnection(conn):
>
> for notif in conn:
> print notif
>
> reactor.stop()
This is an invalid use of inlineCallbacks. Only generator functions
(functions which use `yield`) can be decorated with inlineCallbacks.
>
>c = protocol.ClientCreator(reactor, Notif)
>c.connectTCP("localhost", 6789).addCallback(gotConnection)
>reactor.run()
>
>Except that is does not work: I think that the next() method of the
>generator is indeed automatically called by the "for" machinery but
>its return value is not yielded as the inlineCallbacks requires it.
Quite so. And why would it be? That's not what `for` does in Python.
>
>This works for instance, and it is very close to a for loop:
>
>@defer.inlineCallbacks
>def gotConnection(conn):
>
> while True:
> try:
> print (yield conn.next())
> except StopIteration:
> break
>
>Does someone knows how to make the for loop work with data coming from
>network requests?
You didn't have to switch to a while loop here. The simplest fix for
your for loop is this:
@inlineCallbacks
def gotConnection(conn):
for lineEvent in conn:
line = yield lineEvent
print line
But aside from that...
No, you must have the `yield` somewhere in the function. If you want
something less scrutable than this, then you probably want something
like corotwine.
Jean-Paul
More information about the Twisted-Python
mailing list