Putting the interpreters module under concurrent sounds a bit like putting subprocess under concurrent. It stretches the definitions and makes the structure less readable for the user.
That said, I’m ok with the idea that the SC gets to choose the color of the bikeshed in exchange for their hard work.
We have lots of top level modules that are concurrency related (threading, asyncio, queue, multiprocessing are the ones that most readily come to mind). concurrent.futures was namespaced because a bare top level “futures” module was considered too ambiguous (especially in finance applications).
I don’t think the ambiguity concern for interpreters is as significant as that one, but I was also there for the original discussions when Eric started down this road, so I’m biased towards thinking of the term in the way PEP 734 uses it.
Since we mostly want the public interpreter module as a building block for further work on more inherently threadsafe concurrency models like CSP and the Actor model, namespacing it as being about concurrency strikes me as “not necessary, but not wrong either”.
In my opinion, while individuals who employ multiprocessing, asyncio, or multithreading are explicitly aiming to develop concurrent programs, those who utilise subinterpreters may not necessarily have the same intention. For instance, an individual could create a compact runtime environment to emulate a secure container for executing arbitrary Python code. So I believe placing the multiple interpreters library under the concurrent namespace may limit its perception to solely concurrency, when in reality, its capabilities extend beyond that.
Even if the high-level interface goes in as concurrent.interpreters, there’ll be a low-level interface as _interpreters, which we can actually just document and recommend for special/undiscovered uses by libraries but not “regular” users. That also allows concurrent.interpreters to really lean into the concurrency aspects, e.g. we can add types to it that are useful for coordinating multiple subinterpreters without having to somehow interpret them as being strictly part of the subinterpreters mechanism.
One really easy way to clarify the separation would be to say that _interpreters provides isolation while concurrent.interpreters provides the ways to carefully bridge that isolation.
But I agree with Antoine. While it’s a stretch in terms of purity,[1] it seems the most pragmatic way forward.
(Edit - fixed _interpreters module name.)
Keeping subprocess top-level and putting multiprocessing under concurrent would be more like what I’m proposing. ↩︎
This is likely a documentation issue. As an end user it’s unclear to me why I would use subinterpreters instead of simply using a free threaded thread.
I have a feeling that when one chooses to use subinterpreters, they already know why they’ve chosen to do so and their problem fits the need for using subinterpreters.
Editorial note: the PEP proposes the interpreters name for the module; the current (3.13+) low-level module is called _interpreters, rather than ‘subinterpreters’ for either.
FWIW, putting concurrency-related tools for multiple interpreters under concurrentdoes make sense to me. I can image a variety of future additions that could live in concurrent.interpreters (or concurrent.isolated or whatever). For example, I’d like to have a dedicated module for cross-interpreter queues, for a clearer API than just exposing interpreters.create_queue(), etc. That’s been implemented as interpreters.queues for quite a while (but not a part of PEP 734 nor what I plan to merge for 3.14). Adding that to 3.15 as something like concurrent.interpreters.queue makes some sense.
That said, the specific API from PEP 734–just the minimal interpreters module as proposed–still seems to me as very out of place as concurrent.interpreters. It doesn’t really fit conceptually and I’m not sure why there’s such a push to contort it into place. Perhaps I’m missing something. I do strongly agree with the sentiment that “we should make better use of the concurrent namespace”, but that goal shouldn’t mean we put things there that don’t belong.
FYI, I do plan on merging the change for 3.14 as concurrent.interpreters, to skirt any controversy and get it in now, but I hope I can convince those in the concurrent.interpreters camp in the next few days to move it back to interpreters (or even sys.interpreters if that’s more palatable) for 3.14+.
For me, making the Interpreter class popular is an improvement. The “concurrent” package would be a good place to discover it, but the concurrent.interpreters.Interpreter seems a bit long, at least to learners.
Not strong opinion if multiprocessing or some modules are likely to be included in the package.
I do not know well the history, but I have a concern before landing. Does this feature accept the modules to be imported with a different arbitrary name as below?
(from concurrent) import interpreters as mod1
what1 = mod1.create()
from (concurrent.)interpreters import _queues as mod2
what2 = mod2.create()
Unlike venv.create(), these creations are supposed to be frequent, which could make the code unclear without original module names.
If I understood right, you’re asking if there’s any special alias from interpreters to concurrent.interpreters. Is that right? Or perhaps you are asking if we could add such an alias?
Per the Steering Council, there is no standalone interpreters module. Consequently:
# These work:
import concurrent.interpreters
from concurrent import interpreters
from concurrent import interpreters as mod1
from concurrent.interpreters import ExecutionFailed
# These raise ModuleNotFoundError:
import interpreters
import interpreters as mod1
from interpreters import ExecutionFailed
FWIW, I’m still advocating that the module be top-level, but that’s not what we’re doing (unless something changes last minute).
If you are asking if we could add such an alias, where interpreters and concurrent.interpreters would both work, I don’t think that would happen. We should do one or the other (unless there is some backward-compatibility we need to accommodate).
That said, the docs are always a good place to add links all over the place to drive awareness. (That’s part of why I find the argument of concurrent.interpreters driving awareness to be unconvincing.)
Also, concurrent.interpreters._queue is not part of PEP 734, nor is it a public module in 3.14. Maybe that will change relative to another PEP I’m working on for 3.15. In the meantime, folks will use concurrent.interpreters.create_queue().
Ah, sorry for my poor explanation. I think concurrent.interpreters.create makes sense since the module name includes “interpreters”. Once an alias is used for the module, the create method can become unclear about what it creates. As far as I can see in the code base, only venv and _tkinter modules have create(). create_interp() or something would be clearer but redundant.