Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-134939: Add a Multiple Interpreters Howto Doc#136143

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
ericsnowcurrently wants to merge23 commits intopython:main
base:main
Choose a base branch
Loading
fromericsnowcurrently:multiple-interpreters-howto
Open
Changes from1 commit
Commits
Show all changes
23 commits
Select commitHold shift + click to select a range
96e1e78
Add the multiple interpreters howto doc.
ericsnowcurrentlyJul 16, 2024
e5e980e
Drop extraneous changes.
ericsnowcurrentlyJun 19, 2025
2fcaedd
Finish howto doc, minus recipes.
ericsnowcurrentlyJun 20, 2025
aea8278
Add a TODO list.
ericsnowcurrentlyJun 26, 2025
4bb1e2f
Drop the execcomponents ref.
ericsnowcurrentlyJun 30, 2025
d1ab402
Fix a ref.
ericsnowcurrentlyJun 30, 2025
1c2d40f
Drop the examples section for now.
ericsnowcurrentlyJun 30, 2025
ade2ce3
Fix typos.
ericsnowcurrentlyJul 1, 2025
40f50e7
Add a misc section to the tutorial.
ericsnowcurrentlyJul 1, 2025
0c3105b
Clarify about prepare_main().
ericsnowcurrentlyJul 1, 2025
6028349
Fix a pseudo-ref.
ericsnowcurrentlyJul 1, 2025
d7a7cf0
Fix the examples.
ericsnowcurrentlyJul 1, 2025
fb13944
Tweak one example.
ericsnowcurrentlyJul 1, 2025
72e46fb
Add a ref.
ericsnowcurrentlyJul 2, 2025
675246d
Clarify about Interpreter.exec().
ericsnowcurrentlyJul 3, 2025
22e3ee0
Clarify about calling different kinds of function.
ericsnowcurrentlyJul 3, 2025
f7661da
Clarify a note.
ericsnowcurrentlyJul 3, 2025
28f0218
Add a caveat about -c and the REPL.
ericsnowcurrentlyJul 3, 2025
1b79755
Add a pro tip.
ericsnowcurrentlyJul 3, 2025
b75c380
Add run-examples.py and fix some of the examples.
ericsnowcurrentlySep 23, 2025
35101a0
Do not try reformatting run-examples.py.
ericsnowcurrentlySep 24, 2025
ddae34c
Fix some of the examples.
ericsnowcurrentlySep 24, 2025
652abd3
Do not lint run-examples.py.
ericsnowcurrentlySep 24, 2025
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
PrevPrevious commit
NextNext commit
Clarify about calling different kinds of function.
  • Loading branch information
@ericsnowcurrently
ericsnowcurrently committedJul 3, 2025
commit22e3ee0c4605a7068d60f422cb0e2bc6ce2be7cc

Some comments aren't visible on the classic Files Changed page.

100 changes: 76 additions & 24 deletionsDoc/howto/multiple-interpreters.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -242,7 +242,7 @@ highlighting in your editor. With script text you probably don't.
Calling a Function in an Interpreter
------------------------------------

You can just as easily call a function in another interpreter::
You can just as easily*call* a function in another interpreter::

from concurrent import interpreters

Expand All@@ -254,13 +254,30 @@ You can just as easily call a function in another interpreter::
interp.call(spam)
# prints: spam!

In fact, nearly all Python functions and callables are supported,
with the notable exception of closures. Support includes arguments
and return values, which we'll
:ref:`explore soon <interp-tutorial-return-values>`.
(See :meth:`Interpreter.call`.)

Builtin functions always execute in the target interpreter's
:mod:`!__main__` module::
In fact, nearly all Python functions and callables are supported, with
the notable exclusion of closures. We'll focus on plain functions
for the moment.

Relative to :meth:`Interpreter.call`, there are five kinds of functions:

1. builtin functions
2. extension module functions
3. "stateless" user functions
4. stateful user functions, defined in :mod:`!__main__`
5. stateful user functions, not defined in :mod:`!__main__`

A "stateless" function is one that doesn't use any globals. It also
can't be a closure. It can have parameters but not argument defaults.
It can have return values. We'll cover
:ref:`arguments and returning <interp-tutorial-return-values>` soon.

Some builtin functions, like :func:`exec` and :func:`eval`, use the
current globals as a default (or :func:`implicit <globals>`) argument
value. When such functions are called directly with
:meth:`Interpreter.call`, they use the :mod:`!__main__` module's
:data:`!__dict__` as the default/implicit "globals"::

from concurrent import interpreters

Expand All@@ -272,23 +289,29 @@ Builtin functions always execute in the target interpreter's
interp.call(eval, 'print(__name__)')
# prints: __main__

The same is true for Python functions that don't use any globals::
Note that, for some of those builtin functions, like :func:`globals`
and even :func:`eval` (for some expressions), the return value may
be :ref:`"unshareable" <interp-tutorial-shareable>` and the call will
fail.

from concurrent import interpreters
In each of the above cases, the function is more-or-less copied, when
sent to the other interpreter. For most of the cases, the function's
module is imported in the target interpreter and the function is pulled
from there. The exceptions are cases (3) and (4).

def spam():
# globals is a builtin.
print(globals()['__name__'])

if __name__ == '__main__':
interp = interpreters.create()
interp.call(spam)
# prints: __main__
In case (3), the function is also copied, but efficiently and only
temporarily (long enough to be called) and is not actually bound to
any module. This temporary function object's :data:`!__name__` will
be set to match the code object, but the :data:`!__module__`,
:data:`!__qualname__`, and other attributes are not guaranteed to
be set. This shouldn't be a problem in practice, though, since
introspecting the currently running function is fairly rare.

There are very few cases where that matters, though.
We'll cover case (4) in
:ref:`the next section <interp-tutorial-funcs-in-main>`.

Otherwise, functions defined in modules other than :mod:`!__main__` run
inthat module::
In all the cases, the function will get any global variables from the
module (inthe target interpreter), like normal::

from concurrent import interpreters
from mymod import spam
Expand All@@ -305,9 +328,25 @@ in that module::
def spam():
print(__name__)

For a function actually defined in the :mod:`!__main__` module,
it executes in a separate dummy module, in order to not pollute
the :mod:`!__main__` module::
Note, however, that in case (3) functions rarely look up any globals.

.. _interp-tutorial-funcs-in-main:

Functions Defined in __main__
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
FunctionsDefined in __main__
Functionsdefined in __main__

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

Functions defined in :mod:`!__main__` are treated specially by
:meth:`Interpreter.call`. This is because the script or module that
ran in the main interpreter will have not run in other interpreters,
so any functions defined in the script would only be accessible by
running it in the target interpreter first. That is essentially
how :meth:`Interpreter.call` handles it.

If the function isn't found in the target interpreter's :mod:`!__main__`
module then the script that ran in the main interpreter gets run in the
target interpreter, though under a different name than "__main__".
The function is then looked up on that resulting fake __main__ module.
Comment on lines +352 to +353
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
target interpreter, though under a different name than "__main__".
The function is then looked up on that resulting fake __main__ module.
target interpreter, though under a different name than ":mod:`!__main__`".
The function is then looked up on that resulting fake:mod:`!__main__` module.

For example::

from concurrent import interpreters

Expand All@@ -319,7 +358,12 @@ the :mod:`!__main__` module::
interp.call(spam)
# prints: '<fake __main__>'

This means global state used in such a function won't be reflected
The dummy module is never added to :data:`sys.modules`, though it may
be cached away internally.

This approach with a fake :mod:`!__main__` module means we can avoid
polluting the :mod:`!__main__` module of the target interpreter. It
also means global state used in such a function won't be reflected
in the interpreter's :mod:`!__main__` module::

from textwrap import dedent
Expand DownExpand Up@@ -369,6 +413,12 @@ in the interpreter's :mod:`!__main__` module::
print(total)
# prints: 0

Note that the recommended ``if __name__ == '__main__`:`` idiom is
especially important for such functions, since the script will be
executed with :data:`!__name__` set to something other than
:mod:`!__main__`. Thus, for any code you don't want run repeatedly,
put it in the if block. You will probably only want functions or
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
put it in theif block. You will probably only want functions or
put it in the``if`` block. You will probably only want functions or

classes outside the if block.

Calling Methods and Other Objects in an Interpreter
---------------------------------------------------
Expand DownExpand Up@@ -810,6 +860,8 @@ For example::
assert res is not data
assert data == dict(a=1, b=2, c=3)

.. _interp-tutorial-shareable:

Supported and Unsupported Objects
---------------------------------

Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp