Giter VIP home page Giter VIP logo

Comments (8)

vxgmichel avatar vxgmichel commented on June 2, 2024

Re-implementing asyncio from scratch requires:

  • a selector to handle IO operations
  • an event loop to schedule callbacks
  • futures to represent asynchronous results
  • tasks to run the coroutines

All those concepts are more or less interdependent. I don't see how to explain asyncio coroutines without tasks + futures + event loop, and single-threaded concurrency without a selector.

It's an interesting exercise though, I wonder how long a basic asyncio implementation could be.

from asyncio-doc.

wrobell avatar wrobell commented on June 2, 2024

This is more about concurrent programming model with coroutines than asyncio itself. As you can see, you can run sender and receiver coroutines concurrently and no selector is involved. The example uses sockets, but any other non-IO program could be implemented to explain the model (i.e. the program presented by Knuth in his book).

from asyncio-doc.

vxgmichel avatar vxgmichel commented on June 2, 2024

@wrobell

As you can see, you can run sender and receiver coroutines concurrently and no selector is involved.

Coroutines alone are not enough to provide concurrency. Rather, they can be used along with a cooperative scheduler (i.e an event loop) to implement cooperative multitasking. That also means you need a protocol for the coroutines and the scheduler to communicate. In asyncio, this is done by yielding from a future, which means "please wake me up when this operation is finished".

In your example, you can easily replace the coroutines with regular classes, and it would work the same:

class sender:
    def __init__(self, name):
        self.s = socket.socket()
        self.s.connect(('', PORT))
        self.name = name.encode()

    def send(self, data):
        self.s.send(self.name + b'|' + data.encode())

class receiver:
    def __init__(self, client):
        self.client = client

    def receive(self):
        value = self.client.recv(40)
        client_id, value = value.decode().split('|')
        msg = 'client {}: {}'.format(client_id, value)
        print(msg)

from asyncio-doc.

wrobell avatar wrobell commented on June 2, 2024

Probably we are splitting hairs over definitions here a bit. You can replace "concurrency" with "multitasking" (maybe wording of https://en.wikipedia.org/wiki/Coroutine and http://www.dabeaz.com/coroutines/ will help to explain my position).

You can use classes of course, but then you have to maintain state of your processing on object level - global from class method perspective. Every example provided in presentations at http://www.dabeaz.com/coroutines/ can be reimplemented with classes. Async I/O can be reimplemented with callbacks. But I believe we all agree that coroutines provide better programming model, so we use them and IMHO there is no point to discuss this. :)

It seems we disagree on the need of event loop. Point of my example is that there is no event loop. You can analyze the code of the example and see when and what happens - there is no magic of event loop. It is illustration of multitasking (or concurrency or cooperative execution) with coroutines. Nothing else, nothing more.

The programming model is provided by Python language coroutines. Asyncio uses the model to enable asynchronous I/O programming. IMHO, if we first explain the former, the latter will be easier to understand.

from asyncio-doc.

vxgmichel avatar vxgmichel commented on June 2, 2024

@wrobell

You can replace "concurrency" with "multitasking"

Yes I used them as synonyms, sorry if I didn't make that clear.

But I believe we all agree that coroutines provide better programming model, so we use them and IMHO there is no point to discuss this. :)

Indeed!

It seems we disagree on the need of event loop. Point of my example is that there is no event loop. You can analyze the code of the example and see when and what happens - there is no magic of event loop. It is illustration of multitasking (or concurrency or cooperative execution) with coroutines.

What bothers me in your example is this part:

for i in range(10):
    for s in senders:
        s.send('item {:03d}'.format(i))
    for r in receivers:
        r.send(None)

Things here are executed in a very strict order, so it looks much more like serialized calls than concurrent tasks. I wouldn't call that concurrency, but as you said, it might be a matter of definition.

Anyway, this is how I would illustrate concurrency using coroutines instead.

from asyncio-doc.

wrobell avatar wrobell commented on June 2, 2024

Indeed, the order is quite strict and non-coroutine part of my example is quite long. Would be nice to have shorter example to analyze.

BTW. The following article explains coroutines in Python. If asyncio docs do not have its own description of coroutines, then maybe it would be worth to link to it?
https://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/

from asyncio-doc.

vxgmichel avatar vxgmichel commented on June 2, 2024

That part of the article is quite interesting:

Outside of Python, all but the simplest generators would be referred to as coroutines. I'll use the latter term later in the post. The important thing to remember is, in Python, everything described here as a coroutine is still a generator. Python formally defines the term generator; coroutine is used in discussion but has no formal definition in the language.

Now keep in mind that this article is from 2013, and it was only the beginning of asyncio. Here's what PEP 3156 says about coroutines:

A coroutine is a generator that follows certain conventions. For documentation purposes, all coroutines should be decorated with @asyncio.coroutine , but this cannot be strictly enforced.

Then, in 2015, PEP 492 introduced async/await and coroutines became a proper standalone concept. Python now makes a clear separation between generators and coroutines, since they're different (yet related) concepts used for different purposes. I think we should stick to:

# Native coroutine
async def coro():
    await some_awaitable()

# Generator-based coroutine
@asyncio.coroutine
def coro():
    yield from some_awaitable()

# Since python 3.6: Asynchronous generators
async def gen():
    await some_awaitable()
    yield 1

and call everything else using yield or yield from a generator (or enhanced generator), to avoid confusion.

In my opinion, this article by Brett Cannon would be a better fit for the documentation:

from asyncio-doc.

vstinner avatar vstinner commented on June 2, 2024

I shut down the project: #33

from asyncio-doc.

Related Issues (14)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.