https://github.com/python/cpython/commit/adfde794751ee73d12659d5d408aed59caeda36b
commit: adfde794751ee73d12659d5d408aed59caeda36b
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: hugovk <[email protected]>
date: 2026-04-29T12:56:44+03:00
summary:

[3.14] gh-140287: Handle `PYTHONSTARTUP` script exceptions in the asyncio REPL 
(GH-140288) (#148987)

Co-authored-by: Bartosz SÅ‚awecki <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst
M Lib/asyncio/__main__.py
M Lib/test/test_repl.py

diff --git a/Lib/asyncio/__main__.py b/Lib/asyncio/__main__.py
index 0e100358022a95..44e14771b110d9 100644
--- a/Lib/asyncio/__main__.py
+++ b/Lib/asyncio/__main__.py
@@ -98,11 +98,15 @@ def run(self):
 
             if not sys.flags.isolated and (startup_path := 
os.getenv("PYTHONSTARTUP")):
                 sys.audit("cpython.run_startup", startup_path)
-
-                import tokenize
-                with tokenize.open(startup_path) as f:
-                    startup_code = compile(f.read(), startup_path, "exec")
+                try:
+                    import tokenize
+                    with tokenize.open(startup_path) as f:
+                        startup_code = compile(f.read(), startup_path, "exec")
                     exec(startup_code, console.locals)
+                except SystemExit:
+                    raise
+                except BaseException:
+                    console.showtraceback()
 
             ps1 = getattr(sys, "ps1", ">>> ")
             if CAN_USE_PYREPL:
diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py
index 855dca2258d2a8..16109820beea74 100644
--- a/Lib/test/test_repl.py
+++ b/Lib/test/test_repl.py
@@ -5,6 +5,7 @@
 import subprocess
 import sys
 import unittest
+from contextlib import contextmanager
 from functools import partial
 from textwrap import dedent
 from test import support
@@ -67,6 +68,19 @@ def spawn_repl(*args, stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT, custom=F
 spawn_asyncio_repl = partial(spawn_repl, "-m", "asyncio", custom=True)
 
 
+@contextmanager
+def temp_pythonstartup(*, source: str, histfile: str = ".pythonhist"):
+    """Create environment variables for a PYTHONSTARTUP script in a temporary 
directory."""
+    with os_helper.temp_dir() as tmpdir:
+        filename = os.path.join(tmpdir, "pythonstartup.py")
+        with open(filename, "w") as f:
+            f.write(source)
+        yield {
+            "PYTHONSTARTUP": filename,
+            "PYTHON_HISTORY": os.path.join(tmpdir, histfile)
+        }
+
+
 def run_on_interactive_mode(source):
     """Spawn a new Python interpreter, pass the given
     input source code from the stdin and return the
@@ -276,8 +290,6 @@ def make_repl(env):
         """) % script
         self.assertIn(expected, output)
 
-
-
     def test_runsource_show_syntax_error_location(self):
         user_input = dedent("""def f(x, x): ...
                             """)
@@ -442,6 +454,33 @@ def test_quiet_mode(self):
         self.assertEqual(p.returncode, 0)
         self.assertEqual(output[:3], ">>>")
 
+    @support.force_not_colorized
+    @support.subTests(
+        ("startup_code", "expected_error"),
+        [
+            ("some invalid syntax\n", "SyntaxError: invalid syntax"),
+            ("1/0\n", "ZeroDivisionError: division by zero"),
+        ],
+    )
+    def test_pythonstartup_failure(self, startup_code, expected_error):
+        startup_env = self.enterContext(
+            temp_pythonstartup(source=startup_code, 
histfile=".asyncio_history"))
+
+        p = spawn_repl(
+            "-qm", "asyncio",
+            env=os.environ | startup_env,
+            isolated=False,
+            custom=True)
+        p.stdin.write("print('user code', 'executed')\n")
+        output = kill_python(p)
+        self.assertEqual(p.returncode, 0)
+
+        tb_hint = f'File "{startup_env["PYTHONSTARTUP"]}", line 1'
+        self.assertIn(tb_hint, output)
+        self.assertIn(expected_error, output)
+
+        self.assertIn("user code executed", output)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git 
a/Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst 
b/Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst
new file mode 100644
index 00000000000000..09643956d98093
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst
@@ -0,0 +1,2 @@
+The :mod:`asyncio` REPL now handles exceptions when executing 
:envvar:`PYTHONSTARTUP` scripts.
+Patch by Bartosz Sławecki.

_______________________________________________
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]

Reply via email to