From e4ae72a6d95148f146aaa0a66cd44da42d43c368 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Thu, 23 Apr 2026 21:30:13 +0200 Subject: [PATCH] [3.13] gh-132631: Fix "I/O operation on closed file" when parsing JSON Lines file (GH-132632) (#148922) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Brian Schubert --- Lib/json/tool.py | 3 ++- Lib/test/test_json/json_lines.jsonl | 2 ++ Lib/test/test_json/test_tool.py | 11 ++++++++++- .../2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst | 2 ++ 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 Lib/test/test_json/json_lines.jsonl create mode 100644 Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst diff --git a/Lib/json/tool.py b/Lib/json/tool.py index fdfc3372bcc..e132fc58900 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -63,7 +63,8 @@ def main(): infile = open(options.infile, encoding='utf-8') try: if options.json_lines: - objs = (json.loads(line) for line in infile) + lines = infile.readlines() + objs = (json.loads(line) for line in lines) else: objs = (json.load(infile),) finally: diff --git a/Lib/test/test_json/json_lines.jsonl b/Lib/test/test_json/json_lines.jsonl new file mode 100644 index 00000000000..d2f29211195 --- /dev/null +++ b/Lib/test/test_json/json_lines.jsonl @@ -0,0 +1,2 @@ +{"ingredients":["frog", "water", "chocolate", "glucose"]} +{"ingredients":["chocolate","steel bolts"]} diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index 2b63810d539..231fdfd7626 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -1,4 +1,5 @@ import errno +import pathlib import os import sys import textwrap @@ -6,7 +7,7 @@ import unittest import subprocess from test import support -from test.support import os_helper +from test.support import force_not_colorized, os_helper from test.support.script_helper import assert_python_ok @@ -147,6 +148,14 @@ class TestTool(unittest.TestCase): self.assertEqual(process.stdout, self.jsonlines_expect) self.assertEqual(process.stderr, '') + @force_not_colorized + def test_jsonlines_from_file(self): + jsonl = pathlib.Path(__file__).parent / 'json_lines.jsonl' + args = sys.executable, '-m', 'json.tool', '--json-lines', jsonl + process = subprocess.run(args, capture_output=True, text=True, check=True) + self.assertEqual(process.stdout, self.jsonlines_expect) + self.assertEqual(process.stderr, '') + def test_help_flag(self): rc, out, err = assert_python_ok('-m', 'json.tool', '-h') self.assertEqual(rc, 0) diff --git a/Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst b/Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst new file mode 100644 index 00000000000..9cc1d5a389c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst @@ -0,0 +1,2 @@ +Fix "I/O operation on closed file" when parsing JSON Lines file with +:mod:`JSON CLI `.