Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PEP 0492 - Python 3.5 async keyword

PEP 0492 adds the async keyword to Python 3.5.

How does Python benefit from the use of this operator? The example that is given for a coroutine is

async def read_data(db):
    data = await db.fetch('SELECT ...')

According to the docs this achieves

suspend[ing] execution of read_data coroutine until db.fetch awaitable completes and returns the result data.

Does this async keyword actually involve creation of new threads or perhaps the use of an existing reserved async thread?

In the event that async does use a reserved thread, is it a single shared thread each in their own?

like image 385
Paul Thompson Avatar asked Jul 08 '15 11:07

Paul Thompson


People also ask

How do you use async keyword in Python?

Using await and/or return creates a coroutine function. To call a coroutine function, you must await it to get its results. It is less common (and only recently legal in Python) to use yield in an async def block. This creates an asynchronous generator, which you iterate over with async for .

How do you define async in Python?

An async function uses the await keyword to denote a coroutine. When using the await keyword, coroutines release the flow of control back to the event loop. To run a coroutine, we need to schedule it on the event loop. After scheduling, coroutines are wrapped in Tasks as a Future object.

What is __ Aenter __?

Summary: Python's __aenter__() magic method is semantically identical to __enter__() but is used for asynchronous and parallel programming. Python calls the __aenter__() magic method when starting an async with block whereas the __aexit__() method is called when leaving it.

How do you create a coroutine function in Python?

In Python, coroutines are similar to generators but with few extra methods and slight changes in how we use yield statements. Generators produce data for iteration while coroutines can also consume data. whatever value we send to coroutine is captured and returned by (yield) expression.


1 Answers

No, co-routines do not involve any kind of threads. Co-routines allow for cooperative multi-tasking in that each co-routine yields control voluntarily. Threads on the other hand switch between units at arbitrary points.

Up to Python 3.4, it was possible to write co-routines using generators; by using yield or yield from expressions in a function body you create a generator object instead, where code is only executed when you iterate over the generator. Together with additional event loop libraries (such as asyncio) you could write co-routines that would signal to an event loop that they were going to be busy (waiting for I/O perhaps) and that another co-routine could be run in the meantime:

import asyncio
import datetime

@asyncio.coroutine
def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        yield from asyncio.sleep(1)

Every time the above code advances to the yield from asyncio.sleep(1) line, the event loop is free to run a different co-routine, because this routine is not going to do anything for the next second anyway.

Because generators can be used for all sorts of tasks, not just co-routines, and because writing a co-routine using generator syntax can be confusing to new-comers, the PEP introduces new syntax that makes it clearer that you are writing a co-routine.

With the PEP implemented, the above sample could be written instead as:

async def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(1)

The resulting coroutine object still needs an event loop to drive the co-routines; an event loop would await on each co-routine in turn, which would execute those co-routines that are not currently awaiting for something to complete.

The advantages are that with native support, you can also introduce additional syntax to support asynchronous context managers and iterators. Entering and exiting a context manager, or looping over an iterator then can become more points in your co-routine that signal that other code can run instead because something is waiting again.

like image 171
Martijn Pieters Avatar answered Oct 17 '22 19:10

Martijn Pieters