Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #5656

Re: in search of graceful co-routines

Path csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!selfless.tophat.at!newsfeed.xs4all.nl!newsfeed6.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail
Return-Path <chris@simplistix.co.uk>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.000
X-Spam-Evidence '*H*': 1.00; '*S*': 0.00; 'parameter': 0.05; 'args': 0.07; 'default,': 0.07; 'subject:search': 0.07; 'terry': 0.07; 'twisted,': 0.07; 'variant': 0.07; 'python': 0.08; 'decorator': 0.09; 'none:': 0.09; 'shown.': 0.09; 'throw': 0.09; 'def': 0.12; 'examples': 0.12; 'wrote:': 0.14; 'advance': 0.15; 'arg': 0.16; 'except:': 0.16; 'from:addr:simplistix.co.uk': 0.16; 'from:name:chris withers': 0.16; 'iterator': 0.16; 'message- id:@simplistix.co.uk': 0.16; 'received:89.151': 0.16; 'received:89.151.125': 0.16; 'received:89.151.125.140': 0.16; 'received:server1.simplistix.co.uk': 0.16; 'received:simplistix.co.uk': 0.16; 'reedy': 0.16; 'val': 0.16; 'method.': 0.16; 'cc:addr:python-list': 0.17; 'yield': 0.19; 'cheers,': 0.19; 'header:In-Reply-To:1': 0.21; 'cc:2**0': 0.22; 'cc:no real name:2**0': 0.23; 'closest': 0.23; "doesn't": 0.25; 'certainly': 0.25; 'raise': 0.28; 'skip:_ 20': 0.28; 'mode': 0.29; 'class': 0.29; 'instead': 0.29; 'code,': 0.29; 'bit': 0.30; 'cc:addr:python.org': 0.30; 'considered,': 0.30; 'from:addr:chris': 0.30; 'typeerror:': 0.30; 'print': 0.31; "can't": 0.32; 'cases': 0.32; 'posts': 0.32; 'does': 0.33; "i've": 0.33; 'chris': 0.34; 'file': 0.34; 'however,': 0.34; 'follows:': 0.34; 'that,': 0.34; 'option': 0.35; 'header:User-Agent:1': 0.35; 'skip:" 10': 0.35; 'function.': 0.35; 'itself,': 0.35; 'skip:@ 10': 0.35; 'try:': 0.35; 'using': 0.35; 'none': 0.37; 'feedback': 0.37; 'something': 0.37; 'push': 0.37; 'another': 0.37; 'pretty': 0.37; 'two': 0.37; 'processing': 0.38; 'but': 0.38; 'subject:: ': 0.38; 'received:192': 0.38; 'skip:s 20': 0.39; "i'd": 0.39; 'allows': 0.40; 'received:192.168.1': 0.40; 'more': 0.60; 'url:co': 0.62; 'ready': 0.63; 'believe': 0.66; 'producers': 0.67; 'received:89': 0.68; 'batch': 0.68; 'receive': 0.68; 'reverse': 0.73; 'protect': 0.77; 'seen.': 0.84; 'consumer': 0.85; 'happen:': 0.91
Date Wed, 18 May 2011 07:00:20 +0100
From Chris Withers <chris@simplistix.co.uk>
User-Agent Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.17) Gecko/20110414 Thunderbird/3.1.10
MIME-Version 1.0
To Terry Reedy <tjreedy@udel.edu>
Subject Re: in search of graceful co-routines
References <4DD2AA99.3010508@simplistix.co.uk> <iqv9q2$f13$1@dough.gmane.org>
In-Reply-To <iqv9q2$f13$1@dough.gmane.org>
Content-Type text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding 7bit
Cc python-list@python.org
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.12
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <http://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <http://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Newsgroups comp.lang.python
Message-ID <mailman.1742.1305698415.9059.python-list@python.org> (permalink)
Lines 97
NNTP-Posting-Host 82.94.164.166
X-Trace 1305698415 news.xs4all.nl 49039 [::ffff:82.94.164.166]:50654
X-Complaints-To abuse@xs4all.nl
Xref x330-a1.tempe.blueboxinc.net comp.lang.python:5656

Show key headers only | View raw


On 18/05/2011 03:10, Terry Reedy wrote:
> By default, Python iterators operate in pull mode -- consumers request a
> new item when they want one. I believe .send was mostly intended to
> reverse that, to operate in push mode where producers .send() a item to
> a consumer when they are ready to. That is certainly true of examples I
> have seen.

My first exposure was with the @inlineCallbacks decorator in twisted, 
which does use it both ways...

> Using .send for feedback to a provider is trickier, as the two other
> posts have shown.

The closest I've found to something graceful is:

def mygenerator(*args):
     for arg in args:
         print "yielding:",arg
         result = yield arg
         print "returned:",result
         if result is not None:
             yield None

provider = mygenerator(1,2,3)
for arg in provider:
     print "got:",arg
     if arg%2:
         provider.send('hello')

However, if you do g.send(None), you still get a result back, which 
feels a bit weird...

It's pretty disappointing that neither the send nor throw methods added 
as part of PEP342 were provided with a parameter or variant that did 
"send an item but don't advance the generator".

 > Another option is to write an iterator class instead
> of generator function. You can then give the provider a message receive
> method (.send or whatever) that is decoupled from the send-next method.

Yes, that's an option I'd considered, however, with a provider class as 
follows:

class Provider:

     def __init__(self,*args):
         self.args = args
         self.current = 0

     def next(self):
         try:
             val = self.args[self.current]
         except:
             raise StopIteration()
         self.current += 1
         print "yielding:",val
         return val

     def send(self,value):
         print "returned:",value

     def __iter__(self):
         return self

provider = Provider(1,2,3)
for arg in provider:
     print "got:",arg
     if arg%2:
         provider.send('hello')

...but that's a lot more code, and allows one of my anti-use cases to 
happen:

provider = Provider(1,2,3)
provider.send("don't want this to be possible")

The generator implementation deals with the above specific case:

   File "test.py", line 12, in <module>
     provider.send('hello')
TypeError: can't send non-None value to a just-started generator

...which is, in itself, a little weird, given that it doesn't protect 
against:

provider = Provider(1,2,3)
val = provider.next()
provider.send("don't want this to be possible")
provider.send("don't want this to be possible")

cheers,

Chris

-- 
Simplistix - Content Management, Batch Processing & Python Consulting
            - http://www.simplistix.co.uk

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Re: in search of graceful co-routines Chris Withers <chris@simplistix.co.uk> - 2011-05-18 07:00 +0100

csiph-web