https://github.com/python/cpython/commit/239808c1896e879c8cd58150630325b8d0b0fb65
commit: 239808c1896e879c8cd58150630325b8d0b0fb65
branch: main
author: Peter Bierma <[email protected]>
committer: ZeroIntensity <[email protected]>
date: 2026-10-21T17:16:40-04:00
summary:
gh-158370: Implement the context manager protocol for `Interpreter` objects
(GH-158372)
files:
A Misc/NEWS.d/next/Library/2026-09-28-00-00-00.gh-issue-158370.ctxmgr.rst
M Doc/library/concurrent.interpreters.rst
M Doc/whatsnew/3.16.rst
M Lib/concurrent/interpreters/__init__.py
M Lib/test/test_interpreters/test_api.py
diff --git a/Doc/library/concurrent.interpreters.rst
b/Doc/library/concurrent.interpreters.rst
index 05bf497b68a2082..058e59b32fd15a6 100644
--- a/Doc/library/concurrent.interpreters.rst
+++ b/Doc/library/concurrent.interpreters.rst
@@ -244,6 +244,16 @@ Interpreter objects
Generally, :class:`Interpreter` shouldn't be called directly.
Instead, use :func:`create` or one of the other module functions.
+ :class:`!Interpreter` objects support the :term:`context manager`
+ protocol. Exiting the :keyword:`with` block calls :meth:`close`::
+
+ with interpreters.create() as interp:
+ interp.exec('print("hello")')
+
+ .. versionchanged:: next
+ Added support for using :class:`!Interpreter` objects in
+ a :term:`context manager`.
+
.. attribute:: id
(read-only)
diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst
index b29170b5b0b93da..a0275c9932a282d 100644
--- a/Doc/whatsnew/3.16.rst
+++ b/Doc/whatsnew/3.16.rst
@@ -192,6 +192,13 @@ concurrent.futures
Use the :meth:`!close` method to explicitly close the iterator.
(Contributed by xzmeng and Serhiy Storchaka in :gh:`108518`.)
+concurrent.interpreters
+-----------------------
+
+* :class:`~concurrent.interpreters.Interpreter` objects now support the
+ :term:`context manager` protocol. Exiting the :keyword:`with` block calls
+ :meth:`~concurrent.interpreters.Interpreter.close`.
+ (Contributed by Peter Bierma in :gh:`158370`.)
csv
---
diff --git a/Lib/concurrent/interpreters/__init__.py
b/Lib/concurrent/interpreters/__init__.py
index 335a744b727d100..3053bfbcb122771 100644
--- a/Lib/concurrent/interpreters/__init__.py
+++ b/Lib/concurrent/interpreters/__init__.py
@@ -192,6 +192,12 @@ def close(self):
"""
return _interpreters.destroy(self._id, restrict=True)
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *exc_info):
+ self.close()
+
def prepare_main(self, ns=None, /, **kwargs):
"""Bind the given values into the interpreter's __main__.
diff --git a/Lib/test/test_interpreters/test_api.py
b/Lib/test/test_interpreters/test_api.py
index aac3cdd717668ca..a9e296891bb8705 100644
--- a/Lib/test/test_interpreters/test_api.py
+++ b/Lib/test/test_interpreters/test_api.py
@@ -832,6 +832,31 @@ def task():
assert_python_ok('-c', code)
+class TestInterpreterContextManager(TestBase):
+
+ def test_basic(self):
+ main, = interpreters.list_all()
+ with interpreters.create() as interp:
+ self.assertIsInstance(interp, interpreters.Interpreter)
+ self.assertEqual(interpreters.list_all(), [main, interp])
+ self.assertEqual(interpreters.list_all(), [main])
+ with self.assertRaises(InterpreterNotFoundError):
+ interp.exec('pass')
+
+ def test_exception(self):
+ main, = interpreters.list_all()
+ with self.assertRaises(ZeroDivisionError):
+ with interpreters.create() as interp:
+ 1/0
+ self.assertEqual(interpreters.list_all(), [main])
+
+ def test_main(self):
+ main, = interpreters.list_all()
+ with self.assertRaises(InterpreterError):
+ with main:
+ pass
+
+
class TestInterpreterPrepareMain(TestBase):
def test_empty(self):
diff --git
a/Misc/NEWS.d/next/Library/2026-09-28-00-00-00.gh-issue-158370.ctxmgr.rst
b/Misc/NEWS.d/next/Library/2026-09-28-00-00-00.gh-issue-158370.ctxmgr.rst
new file mode 100644
index 000000000000000..f4b9e2469daa3ed
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-09-28-00-00-00.gh-issue-158370.ctxmgr.rst
@@ -0,0 +1,2 @@
+:class:`concurrent.interpreters.Interpreter` objects now support the
+:term:`context manager` protocol.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]