Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-76785: Multiple Interpreters in the Stdlib (PEP 554) #18817

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions Doc/library/interpreters.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
:mod:`interpreters` --- High-level Subinterpreters Module
==========================================================

.. module:: interpreters
:synopsis: High-level SubInterpreters Module.

**Source code:** :source:`Lib/interpreters.py`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the module going to be provisional still in 3.9 or is this going to be part of the stable API? If it's going to be provisional, I think it could include a note in the header to explain that.

--------------

This module provides high-level tools for working with sub-interpreters,
such as creating them, running code in them, or sending data between them.
It is a wrapper around the low-level `_interpreters` module.

.. versionchanged:: added in 3.9

Interpreter Objects
-------------------

The Interpreter object represents a single interpreter.
.. class:: Interpreter(id)

The class implementing a subinterpreter object.

.. method:: is_running()

Return whether or not the identified interpreter is running.
It returns `True` and `False` otherwise.
Comment on lines +25 to +28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, this could be better phrased as:

Return `True` if the identified interpreter is running.

For comparison, see https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.is_running or https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Future.cancelled.


.. method:: destroy()

Destroy the interpreter. Attempting to destroy the current
interpreter results in a `RuntimeError`.
Comment on lines +30 to +33
Copy link
Contributor

@aeros aeros Mar 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, it also results in a RuntimeError if an interpreter is attempted to be destroyed which is presently running (from my recollection of the C-API function, interp_destroy()). Could this also be mentioned?


.. method:: run(self, src_str, /, *, channels=None):

Run the given source code in the interpreter. This blocks
the current thread until done. `channels` should be in
the form : `(RecvChannel, SendChannel)`.

RecvChannel Objects
-------------------

The RecvChannel object represents a recieving channel.

.. class:: RecvChannel(id)

This class represents the receiving end of a channel.

.. method:: recv()

Get the next object from the channel, and wait if
none have been sent. Associate the interpreter
with the channel.

.. method:: recv_nowait(default=None)

Like ``recv()``, but return the default result
instead of waiting.

.. method:: release()

Release the channel for the current interpreter.
By default both ends are released. Releasing an already
released end results in a ``ChannelReleasedError`` exception.
Comment on lines +61 to +65
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, the second sentence could be better phrased as:

Releasing an end more than once results in a
:exc:`ChannelReleasedError`.

(Also added a Sphinx role, which should generate an inline link to the exception definition below)


.. method:: close(force=False)

Close the channel in all interpreters. By default
both ends are closed. closing an already closed end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
both ends are closed. closing an already closed end
both ends are closed. Closing an already closed end

results in a ``ChannelClosedError`` exception. Without
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
results in a ``ChannelClosedError`` exception. Without
results in a :exc:`ChannelClosedError` exception. Without

seeting ``force`` to ``True`` a ``ChannelNotEmptyError``
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar fix and changed parameter name to use italics instead of backticks. Also adds sphinx role.

Suggested change
seeting ``force`` to ``True`` a ``ChannelNotEmptyError``
setting *force* to ``True``, a :exc:`ChannelNotEmptyError`

will be returned when a channel with data is closed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
will be returned when a channel with data is closed.
will be raised when a channel with data is closed.



SendChannel Objects
--------------------

The ``SendChannel`` object represents a sending channel.

.. class:: SendChannel(id)

This class represents the sending end of a channel.

.. method:: send(obj)

Send the object ``obj`` to the receiving end of the channel
and wait. Associate the interpreter with the channel.

.. method:: send_nowait(obj)

Like ``send()`` but return ``False`` if not received.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phrasing suggestion and clarification:

Suggested change
Like ``send()`` but return ``False`` if not received.
Similar to ``send()``, but returns ``False`` if
*obj* is not immediately received instead of blocking.


.. method:: send_buffer(obj)

Send the object's buffer to the receiving end of the
channel and wait. Associate the interpreter with the
channel.

.. method:: send_buffer_nowait(obj)

Like ``send_buffer()`` but return ``False`` if not received.
Comment on lines +100 to +102
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my above comment on send_nowait().


.. method:: release()

Release the channel for the current interpreter.
By default both ends are released. Releasing an already
released end results in a ``ChannelReleasedError`` exception.
nanjekyejoannah marked this conversation as resolved.
Show resolved Hide resolved

.. method:: close(force=False)

Close the channel in all interpreters. By default
both ends are closed. closing an already closed end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
both ends are closed. closing an already closed end
both ends are closed. Closing an already closed end

results in a ``ChannelClosedError`` exception.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
results in a ``ChannelClosedError`` exception.
results in a :exc:`ChannelClosedError`.



This module defines the following global functions:


.. function:: is_shareable(obj)

Return ``True`` if the object's data can be shared between
interpreters.

.. function:: create_channel()

Create a new channel for passing data between interpreters.

.. function:: list_all_channels()

Return all open channels.
Comment on lines +129 to +131
Copy link
Contributor

@aeros aeros Mar 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this return a list of Channel objects or something else? I think it would be helpful to mention that here.


.. function:: create()

Initialize a new (idle) Python interpreter. Get the currently
running interpreter. This method returns an ``Interpreter`` object.
Comment on lines +133 to +136
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was "Get the currently running interpreter" accidentally included here?


.. function:: get_current()

Get the currently running interpreter. This method returns
an ``Interpreter`` object.

.. function:: list_all()

Get all existing interpreters. Returns a list
of ``Interpreter`` objects.

This module also defines the following exceptions.

.. exception:: RunFailedError

This exception, a subclass of :exc:`RuntimeError`, is raised when the
``Interpreter.run()`` results in an uncaught exception.

.. exception:: ChannelError

This exception is a subclass of :exc:`Exception`, and is the base
class for all channel-related exceptions.

.. exception:: ChannelNotFoundError

This exception is a subclass of :exc:`ChannelError`, and is raised
when the the identified channel is not found.

.. exception:: ChannelEmptyError

This exception is a subclass of :exc:`ChannelError`, and is raised when
the channel is unexpectedly empty.

.. exception:: ChannelNotEmptyError

This exception is a subclass of :exc:`ChannelError`, and is raised when
the channel is unexpectedly not empty.

.. exception:: NotReceivedError

This exception is a subclass of :exc:`ChannelError`, and is raised when
nothing was waiting to receive a sent object.

.. exception:: ChannelClosedError

This exception is a subclass of :exc:`ChannelError`, and is raised when
the channel is closed.

.. exception:: ChannelReleasedError

This exception is a subclass of :exc:`ChannelClosedError`, and is raised
when the channel is released (but not yet closed).
Loading