Add Virtual Threads to Python

That makes me think… why don’t we just get rid of await? async def is fine as a hint your editor can use to fill in the awaits if you want them. Why can’t we approach this problem the way we did with typing?

There is Kotlin that is a prior art of what you described. It has function colouring (suspend a la async) but only on the declaration. The call site does not require an await keyword, and the IDE is responsible for marking the suspension points.

Though you don’t get these indications in e.g., GitHub pull request views or plain text editor.

On the other hand, you have languages like Swift doubling down on async-await, where they use it to signify not only I/O suspensions, but also:

  • non-blocking lock wait and thread hops in their new actor-based data isolation model.
  • region-based isolation for non-concurrency-safe mutable types (like a plain dataclass in Python for instance) at static analysis time to allow race-free data transfer between isolation domains (and indirectly threads because M:N) while preventing unintended concurrent access. (P.S., There has been a PEP discussion alluded to region-based isolation among many other things as well)

Not sure how much of these can apply or is relevant to Python as an interpreted language.

But otherwise, my two cents — coming from a long time Swift & Kotlin background — are that folks should perhaps consider:

  • Separate the discussion on async-await the language syntax (explicit suspension points) from asyncio the implementation (single threaded event loop)
  • Think about the isolation (synchronisation) story once PEP-703 fully opens up the multi-threaded world… maybe draw inspirations from other languages with prior art (e.g., Zig, Rust, Java, Swift, Kotlin), rather than trying to extrapolate more from existing Python code — most of which are de facto built around the shared-nothing, multi-process paradigm.
  • be aware that you have an option to bake virtual threads into the language, but as far as I can tell, that probably comes with another PEP-703 multi-year big surgery. (e.g., all stdlib synchronization primitives need to integrate or provide a version to work with the virtual thread scheduler for non-blocking waits)
  • be aware that you also have an option to achieve a library-level M:N cooperative task runtime on top of the async-await syntax. It likely requires only targeted language changes around coroutines to enable library-level solutions & some thinking in asyncio interop/integration. This is somewhat similar to how Kotlin Coroutines has been happily running on top of JVM as a mostly library-based solution, with fairly thin coroutine support in the Kotlin compiler/language, and without M:N support from JVM. But it does mean “doubling down” on the async function coloring — a problem for some; a blessing for others.
  • Edit: Worth noting that these two options are not mutually exclusive. They can co-exist and interop with each other.
7 Likes