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


Groups > comp.lang.python > #52862

Re: c# async, await

Path csiph.com!usenet.pasdenom.info!weretis.net!feeder4.news.weretis.net!rt.uk.eu.org!newsfeed.xs4all.nl!newsfeed2.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail
Return-Path <ian.g.kelly@gmail.com>
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; 'else:': 0.03; 'argument': 0.05; 'true,': 0.05; '(using': 0.07; 'none,': 0.07; 'none:': 0.07; '*args,': 0.09; '22,': 0.09; 'arguments': 0.09; 'boring': 0.09; 'false,': 0.09; 'try:': 0.09; 'url:archive': 0.09; 'wrapper': 0.09; 'url:blog': 0.10; 'python': 0.11; 'def': 0.12; 'random': 0.14; 'times,': 0.14; 'args,': 0.16; 'callable': 0.16; 'callable.': 0.16; 'caller.': 0.16; 'caveat': 0.16; 'defer': 0.16; 'deferred': 0.16; 'evening,': 0.16; 'indexerror:': 0.16; 'substituted': 0.16; 'terribly': 0.16; 'twisted': 0.16; 'valueerror': 0.16; 'wraps': 0.16; 'wrote:': 0.18; 'thu,': 0.19; 'programming': 0.22; 'import': 0.22; 'aug': 0.22; 'number)': 0.24; 'looks': 0.24; 'sort': 0.25; "i've": 0.25; 'this:': 0.26; 'pass': 0.26; 'gets': 0.27; 'header:In-Reply-To:1': 0.27; 'function': 0.29; 'am,': 0.29; 'raise': 0.29; 'wonder': 0.29; 'message- id:@mail.gmail.com': 0.30; 'along': 0.30; "i'm": 0.30; 'code': 0.31; '(since': 0.31; "they'll": 0.31; 'class': 0.32; 'community': 0.33; 'running': 0.33; 'skip:d 20': 0.34; 'could': 0.34; 'except': 0.35; 'something': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'there': 0.35; 'functions.': 0.36; "he's": 0.36; 'done': 0.36; 'similar': 0.36; 'url:org': 0.36; 'expected': 0.38; 'to:addr :python-list': 0.38; 'anything': 0.39; 'to:addr:python.org': 0.39; 'called': 0.40; 'days': 0.60; 'son': 0.61; 'course': 0.61; 'myself': 0.63; 'side': 0.67; 'promise': 0.68; 'results': 0.69; 'await': 0.74; 'result))': 0.84; 'results,': 0.84; 'url:2013': 0.84; 'numbers:': 0.91; 'have.': 0.93; '2013': 0.98
DKIM-Signature v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; bh=8P3/76ENTJ+Jo4MAnSrvu5dN+JOvkhfhFol3fcrNXDI=; b=RjotPNM8/7faMpj5lXHaqYcCm3URSGDtMHKVB/iILBnkO3g9yqKsPtJHKy0fp9T2e5 c1MYyWiP6rvnRN8ZNyBlw/pJ9HJ0UdIDqedD8WJvz4+PjmB1lNqdFRifN7B5hrlvFhLE ERgO6QCU878UaTxUC7SJvQCkjG3xP+Dq9F7TKeE4YQ2wJMftqmVqX3wP6QKewzKi5iGT C6yc6SYBychbLTWfIL4XDvNfdAl66VoY39SFIqFTGcG2aD3WQP5la68MB3qYAD7Dsund fKVB8PIYmokMc8zG8axt1msvtCPGKYCPgFLALyPxQGxQWAx+4wYC/ME8KX9eEjtqucCS BgTA==
X-Received by 10.52.180.229 with SMTP id dr5mr12181892vdc.20.1377231119228; Thu, 22 Aug 2013 21:11:59 -0700 (PDT)
MIME-Version 1.0
In-Reply-To <kv4sne$p8o$1@ger.gmane.org>
References <kv4sne$p8o$1@ger.gmane.org>
From Ian Kelly <ian.g.kelly@gmail.com>
Date Thu, 22 Aug 2013 22:11:19 -0600
Subject Re: c# async, await
To Python <python-list@python.org>
Content-Type text/plain; charset=ISO-8859-1
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.15
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.150.1377231127.19984.python-list@python.org> (permalink)
Lines 125
NNTP-Posting-Host 2001:888:2000:d::a6
X-Trace 1377231127 news.xs4all.nl 15883 [2001:888:2000:d::a6]:44356
X-Complaints-To abuse@xs4all.nl
Xref csiph.com comp.lang.python:52862

Show key headers only | View raw


On Thu, Aug 22, 2013 at 5:29 AM, Neal Becker <ndbecker2@gmail.com> wrote:
> So my son is now spending his days on c# and .net.  He's enthusiastic about
> async and await, and said to me last evening, "I don't think python has anything
> like that".  I'm not terribly knowledgeable myself regarding async programming
> (since I never need to use it).  I did look at this:
>
> http://tirania.org/blog/archive/2013/Aug-15.html
>
> I wonder what response the python community might have.

I've done something sort of similar to await in Python using
restartable functions.  The code looks like this (using Twisted
Deferreds, but any sort of promise could be substituted in):

from functools import wraps

from twisted.internet import defer


def restartable(func):
    def resume(result, is_failure, results, args, kws):
        def await(get_deferred, *args, **kws):
            try:
                is_failure, result = reversed_results.pop()
            except IndexError:
                raise Await(get_deferred(*args, **kws))
            if is_failure:
                result.raiseException()
            return result

        def do_once(func, *args, **kws):
            return await(defer.maybeDeferred, func, *args, **kws)
        await.do_once = do_once

        if results is None:
            results = []
        else:
            results.append((is_failure, result))
        reversed_results = list(reversed(results))

        try:
            func(await, *args, **kws)
        except Await as exc:
            deferred = exc.args[0]
            deferred.addCallback(resume, False, results, args, kws)
            deferred.addErrback(resume, True, results, args, kws)

    @wraps(func)
    def wrapper(*args, **kws):
        return resume(None, None, None, args, kws)

    return wrapper


class Await(BaseException): pass


The usage of restartable and await then looks something like this:

@restartable
def random_sum(await):
    try:
        a = await(random_number)
        b = await(random_number)
        c = await(random_number)
        d = await(random_number)
    except ValueError as exc:
        print("Couldn't get four numbers: " + exc.message)
        return
    print('{} + {} + {} + {} = {}'.format(a, b, c, d, a + b + c + d))


The "await" argument is passed in by the restartable machinery, not by
the caller.  The argument passed to await is a callable that is
expected to return a Deferred, and any additional arguments are passed
along to the callable.  A boring implementation of the "random_number"
callable might look like this:

def random_number():
    from random import randrange
    from twisted.internet import defer, reactor
    deferred = defer.Deferred()
    if randrange(4) > 0:
        number = randrange(42)
        print("Generated {}".format(number))
        reactor.callLater(1, deferred.callback, number)
    else:
        print("Failed")
        reactor.callLater(1, deferred.errback, ValueError("Not available"))
    return deferred


Of course the big caveat to all this is that since the function is
restartable, the "random_sum" function above actually gets called five
times, and so if there are any side effects before the last await,
they'll end up happening multiple times.  This can be averted using
await.do_once:

@restartable
def random_sum(await):
    try:
        await.do_once(print, 1)
        a = await(random_number)
        await.do_once(print, 2)
        b = await(random_number)
        await.do_once(print, 3)
        c = await(random_number)
        await.do_once(print, 4)
        d = await(random_number)
    except ValueError as exc:
        print("Couldn't get four numbers: " + exc.message)
        return
    print('{} + {} + {} + {} = {}'.format(a, b, c, d, a + b + c + d))

The result of running this is:

1
Generated 35
2
Generated 28
3
Generated 32
4
Generated 16
35 + 28 + 32 + 16 = 111

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


Thread

Re: c# async, await Ian Kelly <ian.g.kelly@gmail.com> - 2013-08-22 22:11 -0600

csiph-web