Hacker News new | ask | show | jobs
by tomchristie 2975 days ago
Neat, good to see more `asyncio` frameworks coming along.

Python's going to have a bit of an awkward time with two completely different sets of ecosystem for threaded vs. asyncio approaches, but it's necessary progress.

One thing I'd be really keen to see is asyncio frameworks starting to consider adopting ASGI as a common interface. Each of quart, sanic, aiohttp currently all have their own gunicorn worker classes, http parsing, and none share the same common interface for handling the request/response interface between server and application.

It's a really high barrier to new asyncio frameworks, and it means we're not able to get shared middleware, such as WSGI's whitenoise or Werkzeug debugger, or the increased robustness that shared server implementations would tend to result in.

Would be interested to know what OP's position on this is?

3 comments

> Python's going to have a bit of an awkward time with two completely different sets of ecosystem for threaded vs. asyncio approaches, but it's necessary progress.

It's threaded vs async/await (and even then projects like https://github.com/dabeaz/curio bridge that gap really well), rather than threaded vs asyncio. asyncio is just one (really really poor) implementation of async/await coroutines on Python.

> One thing I'd be really keen to see is asyncio frameworks starting to consider adopting ASGI as a common interface.

From what I've seen of the ASGI spec, it makes it incredibly easy (like most asyncio stuff) to DoS yourself with lack of backpressure. You get your callback called with data, and like all callback systems you can't exactly not get called.

> It's threaded vs async/await

Fair enough, sure.

> lack of backpressure

You’ll get new calls into the application on new requests, yes. Request bodies are pulled tho.

You can perfectly well ensure that server implementations properly handle flow control, and if necessary also have a configurable number of maximum concurrent requests.

Either way, those sorts of concerns would be far better addressed by having server implementations against a common interface, than by framework authors having to handle (and continually re-implement) the nitty gritty details of high/low watermarks and pausing/resuming transports.

> asyncio is just one (really really poor) implementation of async/await coroutines on Python.

Are there other implementations or is it just that the one existing (asyncio) is just poor?

I tried to understand asyncio a few times and failed. Threading was easy, Promises in JS were easy and I blocked on asyncio.

Me too. Grokked JS promises but async/await threw me. Why is single-threaded async, eg. Node and Python/AsyncIO, such a big deal when we have languages like Elixir, Go and Clojure which have real concurrency and no trade-offs?
There are other implementations, such as Curio (https://github.com/dabeaz/curio) or Trio (https://github.com/python-trio/trio). Both are simpler and more hand-holdy (and less footgun) than asyncio.

Disclaimer: I am a trio dev, though.

Thanks, the trio tutorial is really enlightening!

I was hoping (with Python, not trio in particular) that it would all end up with something like Promises which make coding really easy but I guess not.

This is of course a matter of personal taste, but having

  call_a_asynch_function(with, some, parameters)
  .then(with_the_result_when_it_comes => do_something)
  some_other_codre_which_runs_synchronously
  and_some_more
seems easier to my eye than the whole idea of calling await in async functions
Python doesn't really have the syntax for it, the promise library uses lambda which is pretty bulky: https://pypi.org/project/promise/

I wonder if you could do something nicer using the `with` syntax?

    with async_fn(with, params) as result:
        do_something(result)
    this_runs_sync()
    then_this_does()
It's still going to be annoying when they nest, maybe an async with which makes its whole content act like promises with `then` calls?

    async with fetch_thing() as result:
        json = async_jsonify(result)
        post_result = async_post(json)
        json_result = async_jsonify(post_result)
    then_sync_stuff()
Though you also want to be able to return promises, I suppose you could allow `return async with`, and you also need to be able to catch them. Not sure if this makes any sense to look further at, but I don't think we're getting arrow functions and the JS syntax without those is pretty clunky.
What's wrong with asyncio? For those of us not in the loop.
I'm interested in exploring ASGI as a common interface for Datasette, but I also want the convenience of a neat request and response object. Is there an ASGI equivalent of something like https://webob.org/ yet?
Nope, but probably going to be working towards a library similar to that/werkzeug. Request & Response objects, plus some standard middleware.
more like threaded vs asyncio vs gevent vs tornado vs libuv vs twisted vs multiprocessing