async python

mike warren
https://meejah.ca

async python

review: async

review: event-based programming

Twisted

Deferred

Deferred

from twisted.internet.defer import Deferred
d = Deferred()
def cb(result):
    print("result: {}".format(result))
d.addCallback(cb)
d.callback("the result")
result: the result

Deferred

from twisted.internet.defer import Deferred
d = Deferred()
def err(fail):
    print("error: {}".format(fail.value))
d.addErrback(err)
try:
    1 / 0
except Exception:
    d.errback()
error: division by zero

Twisted Event-Loop

Twisted Event-Loop

Twisted using Deferred

from twisted.internet.defer import Deferred


def main(reactor):
    """
    :returns: a Deferred that fires when the program is completed
    """

    d = Deferred()
    # ...
    return d

Twisted using Deferred

from twisted.internet.defer import Deferred, inlineCallbacks
from twisted.internet.task import react


def main(reactor):
    """
    :returns: a Deferred that fires when the program is completed
    """

    d = Deferred()

    def done(result):
        print("done: {}".format(result))
    d.addCallback(done)

    reactor.callLater(1, d.callback, "the result")
    print("scheduled callback")
    return d


if __name__ == '__main__':
    react(main)
scheduled callback
done: the result

Twisted: @inlineCallbacks

from twisted.internet.defer import Deferred, inlineCallbacks
from twisted.internet.task import react

@inlineCallbacks
def main(reactor):

    d = Deferred()

    reactor.callLater(1, d.callback, "the result")
    print("scheduled callback")
    result = yield d
    print("done: {}".format(result))


if __name__ == '__main__':
    react(main)
scheduled callback
done: the result

Twisted: @inlineCallbacks

from twisted.internet.defer import Deferred, inlineCallbacks
from twisted.internet.task import react

@inlineCallbacks
def main(reactor):

    d = Deferred()

    reactor.callLater(1, d.callback, None)
    print("scheduled callback")
    yield d
    print("done")


if __name__ == '__main__':
    react(main)

asyncio

asyncio

import asyncio

@asyncio.coroutine
def main(loop):

    d = asyncio.Future()

    loop.call_later(1.0, d.set_result, None)
    print("scheduled callback")
    yield from d
    print("done")


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))

async def, await

async def, await

from twisted.internet.defer import ensureDeferred, Deferred
from twisted.internet.task import react

async def main(reactor):

    d = Deferred()

    reactor.callLater(1, d.callback, None)
    print("scheduled callback")
    await d
    print("done")


if __name__ == '__main__':
    def _main(reactor):
        return ensureDeferred(main(reactor))
    react(_main)
scheduled callback
done

async def, await

import asyncio

async def main(loop):

    d = asyncio.Future()

    loop.call_later(1, d.set_result, None)
    print("scheduled callback")
    await d
    print("done")


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))
scheduled callback
done

async *

Coding Exercise

Coding Exercise

import treq

from twisted.internet.defer import Deferred, ensureDeferred
from twisted.internet.task import react
from twisted.web.client import readBody


async def main(reactor):
    # download from a URI
    uri = u"https://meejah.ca"
    response = await treq.get(
        uri,
        headers={
            b"User-Agent": [b"Twisted"],
        }
    )
    # download the reply
    raw_data = await readBody(response)
    print("Received {} bytes".format(len(raw_data)))


if __name__ == '__main__':
    def _main(reactor):
        return ensureDeferred(main(reactor))
    react(_main)

Coding Exercise

import json

import asyncio
import aiohttp


async def main(loop):
    # download from a URL
    url = u"https://meejah.ca"

    async with aiohttp.ClientSession(loop=loop) as session:
        req_context = session.get(
            url,
            headers={
                u"User-Agent": u"asyncio",
            }
        )
        async with req_context as response:
            raw_data = await response.text()

    print("Received {} bytes".format(len(raw_data)))


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))