I would like to clarify whether using
async functions outside of
asyncio is legitimate.
I like using
async functions and
async generators for data processing, as syntactic sugar to create traditional, not-really-async coroutines that can be suspended and resumed.  This can be done with generators, of course, but the quality-of-life improvement using
async pretty much mirrors what is described in PEP 492.
Unfortunately, for most of my applications, using
asyncio is not an option, due to other parallel processing or
multiprocessing constraints. 
Therefore, I run coroutines “by hand”, using
coro.send(None) and so forth. Over time, I have made a little library of tools like
gather(), etc. to do just that. I have now packaged some of these tools up into a small package which I would like to use in one of my main production codes.
Since the inner workings of coroutines do not seem widely advertised, I am wondering whether the fact that coroutines can be resumed using
coro.send(None) and suspended with a bare
yield is an official part of the language, or merely an implementation detail which e.g. PyPy just happens to follow as well.