Skip to content

Commit e5fb655

Browse files
topper-123Terji PetersenTerji Petersenmroeschke
authored
API: ensure read_json closes file handle (#49921)
* API: ensure read_json closes file handle * updates * Update doc/source/whatsnew/v2.0.0.rst Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> Co-authored-by: Terji Petersen <terjipetersen@Terjis-Air.fritz.box> Co-authored-by: Terji Petersen <terjipetersen@Terjis-MacBook-Air.local> Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com>
1 parent fc91090 commit e5fb655

File tree

2 files changed

+27
-24
lines changed

2 files changed

+27
-24
lines changed

doc/source/whatsnew/v2.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ Other API changes
350350
- :func:`read_stata` with parameter ``index_col`` set to ``None`` (the default) will now set the index on the returned :class:`DataFrame` to a :class:`RangeIndex` instead of a :class:`Int64Index` (:issue:`49745`)
351351
- Changed behavior of :class:`Index` constructor with an object-dtype ``numpy.ndarray`` containing all-``bool`` values or all-complex values, this will now retain object dtype, consistent with the :class:`Series` behavior (:issue:`49594`)
352352
- Changed behavior of :meth:`DataFrame.shift` with ``axis=1``, an integer ``fill_value``, and homogeneous datetime-like dtype, this now fills new columns with integer dtypes instead of casting to datetimelike (:issue:`49842`)
353+
- Files are now closed when encountering an exception in :func:`read_json` (:issue:`49921`)
353354
- :meth:`DataFrame.values`, :meth:`DataFrame.to_numpy`, :meth:`DataFrame.xs`, :meth:`DataFrame.reindex`, :meth:`DataFrame.fillna`, and :meth:`DataFrame.replace` no longer silently consolidate the underlying arrays; do ``df = df.copy()`` to ensure consolidation (:issue:`49356`)
354355
-
355356

pandas/io/json/_json.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -750,8 +750,7 @@ def read_json(
750750

751751
if chunksize:
752752
return json_reader
753-
754-
with json_reader:
753+
else:
755754
return json_reader.read()
756755

757756

@@ -896,20 +895,20 @@ def read(self) -> DataFrame | Series:
896895
Read the whole JSON input into a pandas object.
897896
"""
898897
obj: DataFrame | Series
899-
if self.lines:
900-
if self.chunksize:
901-
obj = concat(self)
902-
elif self.nrows:
903-
lines = list(islice(self.data, self.nrows))
904-
lines_json = self._combine_lines(lines)
905-
obj = self._get_object_parser(lines_json)
898+
with self:
899+
if self.lines:
900+
if self.chunksize:
901+
obj = concat(self)
902+
elif self.nrows:
903+
lines = list(islice(self.data, self.nrows))
904+
lines_json = self._combine_lines(lines)
905+
obj = self._get_object_parser(lines_json)
906+
else:
907+
data = ensure_str(self.data)
908+
data_lines = data.split("\n")
909+
obj = self._get_object_parser(self._combine_lines(data_lines))
906910
else:
907-
data = ensure_str(self.data)
908-
data_lines = data.split("\n")
909-
obj = self._get_object_parser(self._combine_lines(data_lines))
910-
else:
911-
obj = self._get_object_parser(self.data)
912-
self.close()
911+
obj = self._get_object_parser(self.data)
913912
return obj
914913

915914
def _get_object_parser(self, json) -> DataFrame | Series:
@@ -964,24 +963,27 @@ def __next__(self: JsonReader[Literal["frame", "series"]]) -> DataFrame | Series
964963
...
965964

966965
def __next__(self) -> DataFrame | Series:
967-
if self.nrows:
968-
if self.nrows_seen >= self.nrows:
969-
self.close()
970-
raise StopIteration
966+
if self.nrows and self.nrows_seen >= self.nrows:
967+
self.close()
968+
raise StopIteration
971969

972970
lines = list(islice(self.data, self.chunksize))
973-
if lines:
971+
if not lines:
972+
self.close()
973+
raise StopIteration
974+
975+
try:
974976
lines_json = self._combine_lines(lines)
975977
obj = self._get_object_parser(lines_json)
976978

977979
# Make sure that the returned objects have the right index.
978980
obj.index = range(self.nrows_seen, self.nrows_seen + len(obj))
979981
self.nrows_seen += len(obj)
982+
except Exception as ex:
983+
self.close()
984+
raise ex
980985

981-
return obj
982-
983-
self.close()
984-
raise StopIteration
986+
return obj
985987

986988
def __enter__(self) -> JsonReader[FrameSeriesStrT]:
987989
return self

0 commit comments

Comments
 (0)