For those unaware of asynchronous programming, we could say it's a way to achieve a certain level of multi-tasking within a single process or thread. It leverages the fact that our typical processes spend a lot of their time waiting for input/ouput (I/O) operations to complete. The kind of operation involving I/O includes receiving requests from clients, reading files, querying a database server or talking to a RESTful API. Instead of waiting for each I/O operation to complete before starting the next one, asynchronous programming allow a single process to schedule several such operations in parallel.

This is similar to how you may prepare your breakfast. You probably don't wait for coffee or tea to be ready before starting your toaster or rice cooker. You start both operations in parallel and get notified by an event (kettle whistling, bread popping out) when they've completed. This way you can multitask effectively even though you're a single "process".

Let's start with a Hello World example using asyncio.sleep to simulate slow I/O operations and asyncio.wait to launch them in parallel. This is how it would look like before Python 3.5:

import asyncio @asyncio.coroutine def slow_operation ( n ): yield from asyncio . sleep ( 1 ) print ( "Slow operation {} complete" . format ( n )) @asyncio.coroutine def main (): yield from asyncio . wait ([ slow_operation ( 1 ), slow_operation ( 2 ), slow_operation ( 3 ), ]) loop = asyncio . get_event_loop () loop . run_until_complete ( main ())

As you can see, this example uses existing Python syntax: decorators and the yield keyword.

Running this script gives us this output:

$ python3.4 sleeping.py Slow operation 1 complete Slow operation 2 complete Slow operation 3 complete

Now here is how the code may look like using the upcoming version 3.5 of Python:

import asyncio async def slow_operation ( n ): await asyncio . sleep ( 1 ) print ( "Slow operation {} complete" . format ( n )) async def main (): await asyncio . wait ([ slow_operation ( 1 ), slow_operation ( 2 ), slow_operation ( 3 ), ]) loop = asyncio . get_event_loop () loop . run_until_complete ( main ())

The new async and await keywords make it more clear that we're dealing with asynchronous code rather than regular generators.

Let's run this script (with Python 3.5):

$ python3.5 sleeping-awaitasync.py Slow operation 2 complete Slow operation 3 complete Slow operation 1 complete

Now for a slightly more realistic example, we'll implement a web server that makes sub-requests to external HTTP services. We could imagine it evolving into a website monitoring app. We'll use aiohttp, an HTTP client/server for asyncio:

import asyncio import aiohttp from aiohttp import web import json WEBSITES = [ 'http://example.com/' , 'http://dummy-a98x3.org' , 'http://example.net/' ] async def handle ( request ): # Fire up 3 requests in parallel coroutines = [ aiohttp . request ( 'get' , website ) for website in WEBSITES ] # Wait for those requests to complete results = await asyncio . gather ( * coroutines , return_exceptions = True ) # Analyze results response_data = { website : not isinstance ( result , Exception ) and result . status == 200 for website , result in zip ( WEBSITES , results ) } # Build JSON response body = json . dumps ( response_data ) . encode ( 'utf-8' ) return web . Response ( body = body , content_type = "application/json" ) loop = asyncio . get_event_loop () app = web . Application ( loop = loop ) app . router . add_route ( 'GET' , '/' , handle ) server = loop . create_server ( app . make_handler (), '127.0.0.1' , 8000 ) print ( "Server started at http://127.0.0.1:8000" ) loop . run_until_complete ( server ) try : loop . run_forever () except KeyboardInterrupt : pass

Let's start the server:

$ python3.5 server.py Server started at http://127.0.0.1:8000

And send it a request:

$ curl http://127.0.0.1:8000 {"http://example.com/": true, "http://example.net/": true, "http://dummy-a98x3.org": false}

That's it for today. I hope this got you excited about the new Python async/await syntax. Now go read the spec or grab the pre-releasse and have fun!