2

I'm writing a Sublime Text plugin that provides multiple Python shells accessible via UNIX sockets. Each shell should act as a standalone REPL running on its own thread. (It is undesirable for these shells to have their own processes; sharing a single process is an absolute requirement.)

The builtin exec() function prints output to stdout if the code was compiled with mode='single' and is an expression that does not evaluate to None. I need to send this output over the socket instead.

I know that this can be done by patching stdout. However, this would not work here because multiple consoles may be running in multiple threads (plus the built-in console).

My ideas are as follows:

  • Try to compile() the input with mode='eval', eval() it, and print the result (if not None). If it won't compile, try mode='exec' instead of mode='single'.
  • For each console's thread, keep the output stream in thread-local storage. Patch sys.stdout with an object that checks for these streams before calling "regular" stdout.
  • Somehow provide a patched sys to each console.

These don't seem like great ideas. Is there a better one?

Thom Smith
  • 13,916
  • 6
  • 45
  • 91
  • 2
    These shells are never going to be anywhere near as independent as you're hoping. (Also, `exec` doesn't auto-print expression values.) – user2357112 Feb 27 '19 at 21:12
  • It does if the code was compiled with `mode='single'`, which I forgot to mention (now in the question). I'm aware that it won't be perfect, but I'm willing to settle for a definition of "reasonably good" that includes echoing the output. – Thom Smith Feb 27 '19 at 21:16
  • Run each of the REPLs in a seperate python process with its own pty. Have your master copy to and from the ptys and the Unix sockets. Attempting to do this without processes is working against the design of Unix. – Dan D. Feb 27 '19 at 21:39
  • With `mode='single'`, yeah, you'd get autoprinting. – user2357112 Feb 27 '19 at 21:43

1 Answers1

1

If you're dead set on having a single process, then depending on how willing you are to dive into obscure C-level features of the CPython implementation, you might try looking into subinterpreters. Those are, as far as I know, the highest level of isolation CPython provides in a single process, and they allow things like separate sys.stdout objects for separate subinterpreters.

user2357112
  • 260,549
  • 28
  • 431
  • 505