Skip to content

Commit 00a535d

Browse files
authored
Merge branch 'main' into docs/pep750-first-pass
2 parents 7b660be + f273fd7 commit 00a535d

124 files changed

Lines changed: 2888 additions & 1583 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/CODEOWNERS

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,13 @@ Doc/howto/clinic.rst @erlend-aasland
281281
# Subinterpreters
282282
**/*interpreteridobject.* @ericsnowcurrently
283283
**/*crossinterp* @ericsnowcurrently
284-
Lib/test/support/interpreters/ @ericsnowcurrently
285284
Modules/_interp*module.c @ericsnowcurrently
285+
Lib/test/test__interp*.py @ericsnowcurrently
286+
Lib/concurrent/interpreters/ @ericsnowcurrently
287+
Lib/test/support/channels.py @ericsnowcurrently
288+
Doc/library/concurrent.interpreters.rst @ericsnowcurrently
286289
Lib/test/test_interpreters/ @ericsnowcurrently
290+
Lib/concurrent/futures/interpreter.py @ericsnowcurrently
287291

288292
# Android
289293
**/*Android* @mhsmith @freakboy3742

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ Tools/unicode/data/
131131
/autom4te.cache
132132
/build/
133133
/builddir/
134+
/compile_commands.json
134135
/config.cache
135136
/config.log
136137
/config.status

Doc/c-api/init.rst

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -492,17 +492,8 @@ Initializing and finalizing the interpreter
492492
strings other than those passed in (however, the contents of the strings
493493
pointed to by the argument list are not modified).
494494
495-
The return value will be ``0`` if the interpreter exits normally (i.e.,
496-
without an exception), ``1`` if the interpreter exits due to an exception,
497-
or ``2`` if the argument list does not represent a valid Python command
498-
line.
499-
500-
Note that if an otherwise unhandled :exc:`SystemExit` is raised, this
501-
function will not return ``1``, but exit the process, as long as
502-
``Py_InspectFlag`` is not set. If ``Py_InspectFlag`` is set, execution will
503-
drop into the interactive Python prompt, at which point a second otherwise
504-
unhandled :exc:`SystemExit` will still exit the process, while any other
505-
means of exiting will set the return value as described above.
495+
The return value is ``2`` if the argument list does not represent a valid
496+
Python command line, and otherwise the same as :c:func:`Py_RunMain`.
506497
507498
In terms of the CPython runtime configuration APIs documented in the
508499
:ref:`runtime configuration <init-config>` section (and without accounting
@@ -539,23 +530,18 @@ Initializing and finalizing the interpreter
539530
540531
If :c:member:`PyConfig.inspect` is not set (the default), the return value
541532
will be ``0`` if the interpreter exits normally (that is, without raising
542-
an exception), or ``1`` if the interpreter exits due to an exception. If an
543-
otherwise unhandled :exc:`SystemExit` is raised, the function will immediately
544-
exit the process instead of returning ``1``.
533+
an exception), the exit status of an unhandled :exc:`SystemExit`, or ``1``
534+
for any other unhandled exception.
545535
546536
If :c:member:`PyConfig.inspect` is set (such as when the :option:`-i` option
547537
is used), rather than returning when the interpreter exits, execution will
548538
instead resume in an interactive Python prompt (REPL) using the ``__main__``
549539
module's global namespace. If the interpreter exited with an exception, it
550540
is immediately raised in the REPL session. The function return value is
551-
then determined by the way the *REPL session* terminates: returning ``0``
552-
if the session terminates without raising an unhandled exception, exiting
553-
immediately for an unhandled :exc:`SystemExit`, and returning ``1`` for
554-
any other unhandled exception.
555-
556-
This function always finalizes the Python interpreter regardless of whether
557-
it returns a value or immediately exits the process due to an unhandled
558-
:exc:`SystemExit` exception.
541+
then determined by the way the *REPL session* terminates: ``0``, ``1``, or
542+
the status of a :exc:`SystemExit`, as specified above.
543+
544+
This function always finalizes the Python interpreter before it returns.
559545
560546
See :ref:`Python Configuration <init-python-config>` for an example of a
561547
customized Python that always runs in isolated mode using

Doc/c-api/typeobj.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,26 @@ and :c:data:`PyType_Type` effectively act as defaults.)
686686
instance, and call the type's :c:member:`~PyTypeObject.tp_free` function to
687687
free the object itself.
688688

689+
If you may call functions that may set the error indicator, you must use
690+
:c:func:`PyErr_GetRaisedException` and :c:func:`PyErr_SetRaisedException`
691+
to ensure you don't clobber a preexisting error indicator (the deallocation
692+
could have occurred while processing a different error):
693+
694+
.. code-block:: c
695+
696+
static void
697+
foo_dealloc(foo_object *self)
698+
{
699+
PyObject *et, *ev, *etb;
700+
PyObject *exc = PyErr_GetRaisedException();
701+
...
702+
PyErr_SetRaisedException(exc);
703+
}
704+
705+
The dealloc handler itself must not raise an exception; if it hits an error
706+
case it should call :c:func:`PyErr_FormatUnraisable` to log (and clear) an
707+
unraisable exception.
708+
689709
No guarantees are made about when an object is destroyed, except:
690710

691711
* Python will destroy an object immediately or some time after the final

Doc/c-api/unicode.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1827,7 +1827,7 @@ object.
18271827
On success, return ``0``.
18281828
On error, set an exception, leave the writer unchanged, and return ``-1``.
18291829
1830-
.. versionadded:: next
1830+
.. versionadded:: 3.14
18311831
18321832
.. c:function:: int PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, const wchar_t *str, Py_ssize_t size)
18331833

Doc/library/calendar.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is
251251
3) specifies the number of months per row. *css* is the name for the
252252
cascading style sheet to be used. :const:`None` can be passed if no style
253253
sheet should be used. *encoding* specifies the encoding to be used for the
254-
output (defaulting to the system default encoding).
254+
output (defaulting to ``'utf-8'``).
255255

256256

257257
.. method:: formatmonthname(theyear, themonth, withyear=True)

Doc/library/concurrency.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ multitasking). Here's an overview:
1818
multiprocessing.shared_memory.rst
1919
concurrent.rst
2020
concurrent.futures.rst
21+
concurrent.interpreters.rst
2122
subprocess.rst
2223
sched.rst
2324
queue.rst
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
:mod:`!concurrent.interpreters` --- Multiple interpreters in the same process
2+
=============================================================================
3+
4+
.. module:: concurrent.interpreters
5+
:synopsis: Multiple interpreters in the same process
6+
7+
.. moduleauthor:: Eric Snow <ericsnowcurrently@gmail.com>
8+
.. sectionauthor:: Eric Snow <ericsnowcurrently@gmail.com>
9+
10+
.. versionadded:: 3.14
11+
12+
**Source code:** :source:`Lib/concurrent/interpreters.py`
13+
14+
--------------
15+
16+
17+
Introduction
18+
------------
19+
20+
The :mod:`!concurrent.interpreters` module constructs higher-level
21+
interfaces on top of the lower level :mod:`!_interpreters` module.
22+
23+
.. XXX Add references to the upcoming HOWTO docs in the seealso block.
24+
25+
.. seealso::
26+
27+
:ref:`isolating-extensions-howto`
28+
how to update an extension module to support multiple interpreters
29+
30+
:pep:`554`
31+
32+
:pep:`734`
33+
34+
:pep:`684`
35+
36+
.. XXX Why do we disallow multiple interpreters on WASM?
37+
38+
.. include:: ../includes/wasm-notavail.rst
39+
40+
41+
Key details
42+
-----------
43+
44+
Before we dive into examples, there are a small number of details
45+
to keep in mind about using multiple interpreters:
46+
47+
* isolated, by default
48+
* no implicit threads
49+
* not all PyPI packages support use in multiple interpreters yet
50+
51+
.. XXX Are there other relevant details to list?
52+
53+
In the context of multiple interpreters, "isolated" means that
54+
different interpreters do not share any state. In practice, there is some
55+
process-global data they all share, but that is managed by the runtime.
56+
57+
58+
Reference
59+
---------
60+
61+
This module defines the following functions:
62+
63+
.. function:: list_all()
64+
65+
Return a :class:`list` of :class:`Interpreter` objects,
66+
one for each existing interpreter.
67+
68+
.. function:: get_current()
69+
70+
Return an :class:`Interpreter` object for the currently running
71+
interpreter.
72+
73+
.. function:: get_main()
74+
75+
Return an :class:`Interpreter` object for the main interpreter.
76+
77+
.. function:: create()
78+
79+
Initialize a new (idle) Python interpreter
80+
and return a :class:`Interpreter` object for it.
81+
82+
83+
Interpreter objects
84+
^^^^^^^^^^^^^^^^^^^
85+
86+
.. class:: Interpreter(id)
87+
88+
A single interpreter in the current process.
89+
90+
Generally, :class:`Interpreter` shouldn't be called directly.
91+
Instead, use :func:`create` or one of the other module functions.
92+
93+
.. attribute:: id
94+
95+
(read-only)
96+
97+
The interpreter's ID.
98+
99+
.. attribute:: whence
100+
101+
(read-only)
102+
103+
A string describing where the interpreter came from.
104+
105+
.. method:: is_running()
106+
107+
Return ``True`` if the interpreter is currently executing code
108+
in its :mod:`!__main__` module and ``False`` otherwise.
109+
110+
.. method:: close()
111+
112+
Finalize and destroy the interpreter.
113+
114+
.. method:: prepare_main(ns=None, **kwargs)
115+
116+
Bind "shareable" objects in the interpreter's
117+
:mod:`!__main__` module.
118+
119+
.. method:: exec(code, /, dedent=True)
120+
121+
Run the given source code in the interpreter (in the current thread).
122+
123+
.. method:: call(callable, /, *args, **kwargs)
124+
125+
Return the result of calling running the given function in the
126+
interpreter (in the current thread).
127+
128+
.. method:: call_in_thread(callable, /, *args, **kwargs)
129+
130+
Run the given function in the interpreter (in a new thread).
131+
132+
Exceptions
133+
^^^^^^^^^^
134+
135+
.. exception:: InterpreterError
136+
137+
This exception, a subclass of :exc:`Exception`, is raised when
138+
an interpreter-related error happens.
139+
140+
.. exception:: InterpreterNotFoundError
141+
142+
This exception, a subclass of :exc:`InterpreterError`, is raised when
143+
the targeted interpreter no longer exists.
144+
145+
.. exception:: ExecutionFailed
146+
147+
This exception, a subclass of :exc:`InterpreterError`, is raised when
148+
the running code raised an uncaught exception.
149+
150+
.. attribute:: excinfo
151+
152+
A basic snapshot of the exception raised in the other interpreter.
153+
154+
.. XXX Document the excinfoattrs?
155+
156+
.. exception:: NotShareableError
157+
158+
This exception, a subclass of :exc:`TypeError`, is raised when
159+
an object cannot be sent to another interpreter.
160+
161+
162+
.. XXX Add functions for communicating between interpreters.
163+
164+
165+
Basic usage
166+
-----------
167+
168+
Creating an interpreter and running code in it::
169+
170+
from concurrent import interpreters
171+
172+
interp = interpreters.create()
173+
174+
# Run in the current OS thread.
175+
176+
interp.exec('print("spam!")')
177+
178+
interp.exec("""if True:
179+
print('spam!')
180+
""")
181+
182+
from textwrap import dedent
183+
interp.exec(dedent("""
184+
print('spam!')
185+
"""))
186+
187+
def run():
188+
print('spam!')
189+
190+
interp.call(run)
191+
192+
# Run in new OS thread.
193+
194+
t = interp.call_in_thread(run)
195+
t.join()
196+
197+
198+
.. XXX Explain about object "sharing".

Doc/library/concurrent.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
The :mod:`!concurrent` package
22
==============================
33

4-
Currently, there is only one module in this package:
4+
This package contains the following modules:
55

66
* :mod:`concurrent.futures` -- Launching parallel tasks
7+
* :mod:`concurrent.interpreters` -- Multiple interpreters in the same process

Doc/library/csv.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ A slightly more advanced use of the reader --- catching and reporting errors::
609609
for row in reader:
610610
print(row)
611611
except csv.Error as e:
612-
sys.exit('file {}, line {}: {}'.format(filename, reader.line_num, e))
612+
sys.exit(f'file {filename}, line {reader.line_num}: {e}')
613613

614614
And while the module doesn't directly support parsing strings, it can easily be
615615
done::

0 commit comments

Comments
 (0)