3 ms·
I'll bite. Opinion follows, no need to downvote. async def is terrible, of the syntactic/semantic options it is the worst. Best would have been to just allow
by jonahbenton 6y ago
I'll bite. Opinion follows, no need to downvote.
async def
is terrible, of the syntactic/semantic options it is the worst.
Best would have been to just allow creation of a name of a coroutine-usable version of a function-
def f: # normal f
....
a = async(f)
That allows existing functions to be turned into coroutines while not introducing the new syntactic pattern of a double word declaration.
- takeda 6y agoYou still can do that using @asyncio.coroutine decorator for example @asyncio.coroutine def hello(): return "foo" Although not for long, they deprecated it in 3.8 and will be removed in 3.10. I wish they would leave it, since I was able to use them to write API that could be synchronous or not depending which constructor was invoked. I'm wondering if there are better ways to do it.
- deleted 6y ago[deleted]
- oefrha 6y agoYou can write a trivial decorator to make any normal blocking function async-usable (i.e. your suggestion is possible today and only takes a few lines of code — not even using deprecated functionality, I mean), but that doesn’t magically make it async-capable if it’s not designed for async in the first place. If you’re arguing for generator-based coroutines, then (1) that’s not just any normal function (check inspect.isgeneratorfunction and inspect.iscoroutinefunction); (2) it was already explored and deprecated. Guess we can have another talk on why if you wish.
- jonahbenton 6y agoSure, there are a few different issues here, and my response above was mostly off the cuff. I have had the pleasure of engaging with cooperative vs scheduled concurrency since the 1980s, in the early days of the Mac, and asynchronous IO since it started to enter the mainstream in the 1990s. I don't write enough python any more that this impacts me much; more that I remember finding out about it and being astonished. That's not to say- the async PEP is well written and one gets the mental model the author is promoting and the problems the PEP is trying to solve. I used tornado a bunch in its early days and it was and I'm sure still is a lovely piece of engineering. Nevertheless, among the reasons for my astonishment were: * there is a difference between cooperative concurrency and largely IO-scheduling driven asynchrony. There are a range of protocols that callers and callees engage in, a level of greater or lesser interest that the caller has on what and when the callee does it, and a variety of ways the callee can make what it did more or less eventually known to the caller. Cooperation and async capture two distinct common use cases in this rich space, yet the python implementation seems to improperly lump the two together. And the added keywords are crude and only provide partial expression of the range of options. For instance, deadlines are a top level consideration both in cooperation and in asynchrony, yet there is no syntax for specifying them. * there is a level of sophistication required for effective cooperative or asynchronous programming that, despite the rise of node and so forth, is simply not met by the bulk of programmers employing it, nor necessary in the programs they are writing. Elevating the syntax to first class as though it is something for most python programmers to consider- well, you can have a synchronous function, or an asynchronous function, pick one- is putting power tools in the hands of people who mostly don't know how to use them working on problems that entirely don't need them. Especially for python, this seems like the wrong thing to have done. * the doubled keywords pattern is ugly. Yes, if you are going to allow for cooperative behavior, decorating the affected syntactic entities is necessary. If it had to get added to the language I would much rather have seen new single tokens- adef and afor- for this purpose, maybe added to an "expert" module to be "imported" before use. With a whole new declarative keyword, one asks- what else can this be applied to? Why not have async variables or instance members? The syntax suggests itself and there are potential semantics. Forgive me, but I was shocked when I saw this and still think it was an immature and unnecessary addition to the language.
- oefrha 6y agoThese are reasonable arguments but I largely disagree as someone who might not meet your threshold of sophistication. * Apparently the "crude" syntax is supplemented by an asyncio library providing more fine grained controls without further complicating Python syntax. * I don't think gatekeeping is a very good argument against a language feature. Obviously Node is special because it forces you to use async even if you just want to write boring old blocking code, but in Python this is strictly optional, and having it as a language feature doesn't mean "most Python programmers" are suddenly going to consider it, just like most Python programmers don't consider metaclasses. I'm certain the vast majority of Python programmers aren't having this inner debate of "you can have a synchronous function, or an asynchronous function, pick one"; it's been five years and four major Python versions and I've never heard anyone complaining about this choice when it's not relevant. * Meanwhile, I've personally used native asyncio for both of your distinct common use cases (replaced threading-based solutions, saw saner code and some performance improvements), so I consider it a success. * Ugliness is subjective, I'd say adef/afor/awith/etc. are more of a wtf if I'm new to the language, and you end up with more keywords. The async keyword also leaves the door open; async def/with were introduced in py35 while async for was introduced in py36, so it is conceivable that the async keyword could be expanded to more use cases in the future.
- jonahbenton 6y agoThanks, fair points, no offense intended.
- oefrha 6y agoNone taken, I honestly don’t think I’m very sophisticated when it comes to async and concurrency (but I do benefit from being served).
- fnord123 6y agoHow would you implement async() under the covers? If you wanted something like go (or loom) then wouldn't you need stack swapping? And if you have those then you muddy Python's #1 best feature: the almost free C ffi.