https://github.com/python/cpython/commit/5ea3ae7c97f06cebcbbe81b142ee4a2b23d980e9
commit: 5ea3ae7c97f06cebcbbe81b142ee4a2b23d980e9
branch: main
author: Bartosz Sławecki <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-04-25T15:24:40+01:00
summary:
gh-140287: Handle `PYTHONSTARTUP` script exceptions in the asyncio REPL
(#140288)
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 8ee09b38469d4c..37eba9657ac5a8 100644
--- a/Lib/asyncio/__main__.py
+++ b/Lib/asyncio/__main__.py
@@ -101,11 +101,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 27cd125078ea69..850cb66a89ba84 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): ...
""")
@@ -449,6 +461,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]