I would like to be able to have multiple async REPLs running within the same interpreter. Each async REPL would be bound to a tty which is sent to it via a Unix-domain socket. This would be very handy when working with a large, multi-faceted, long-running daemon.
Unfortunately, I have identified five key obstacles to this:
Only one sys.std{in|out|err}
This turns out to be relatively easy to fix with a file-like proxy that forwards via a contextvar, though perhaps a more elegant/performant solution could be found, especially as printing to different places by default in each context has obvious broader usefulness.
Only one _
I suspect this could be attacked similarly by making sys.displayhook a proxy to a per-REPL contextvar that writes to that contextās globals()._but it turns out to be very hard to test this without a working multi-REPL framework in which to try it.
Only one readline
Before 3.13 this appeared to be an almost insurmountable show-stopper: GNU readline only supports one instance per process. The two least-bad options would be to reimplement readline from scratch or maintain a separate process instead of merely a separate thread for the REPLās main loop. Neither of those seemed attractive, so I shelved my idea.
But 3.13 brought the shiny new REPL with a new, far more capable, input handler implemented natively in Python. Sadly that, too, appears to expect only one instance to be running. It might be easier to hack on, but there would need to be support for integrating those changes back into the _repl module so the hack didnāt diverge.
The asyncio module doesnāt expose its REPL
As noted in this previous topic, most of the logic behind python -m asyncio is contained within an if __name__ == '__main__' beyond the reach of easy use from other Python code. This is a pity since it would be nice to be able to stably reuse the logic for running the REPL in one thread, but invoking any code executions against the running program to another (the main) thread.
Itās not much code, so it could be cloned and hacked on, except that sinceā¦
The _repl module has no documented/stable API
ā¦any custom code derived from python -m asyncio or written along similar lines canāt stably invoke the _repl module; the asyncio module is closely coupled to it.
Soā¦
The dream would be for the asyncio module to provide an await asyncio.repl(tty) function that manages the entire process of launching a REPL on that TTY and running it to orderly completion.
Absent that, the minimum viable product would be a documented interface to _repl that supported multiple instances.
Am I a freak for wanting this, or is it an itch other people are also scratching? The code module is recognised as useful enough to be worth exposing; it feels like there should be similar support for async REPLs and supporting multiple simultaneous instances is very much expected in such an environment.