Skip to content

Commit 2f3df3a

Browse files
frexvahiTomAugspurger
authored andcommitted
Fix reading Series with read_hdf (pandas-dev#16610)
* Added test to reproduce issue pandas-dev#16583 * Fix pandas-dev#16583 by adding an explicit `mode` argument to `read_hdf` kwargs which are meant for the opening of the HDFStore should be filtered out before passing the remaining kwargs to the `select` function to load the data. * Noted fix for pandas-dev#16583 in WhatsNew (cherry picked from commit 196eb8e)
1 parent 9365d1f commit 2f3df3a

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

doc/source/whatsnew/v0.20.3.txt

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ I/O
5656
^^^
5757

5858
-- Bug in ``pd.read_csv()`` in which files weren't opened as binary files by the C engine on Windows, causing EOF characters mid-field, which would fail (:issue:`16039`, :issue:`16559`, :issue`16675`)
59+
-- Bug in ``pd.read_hdf()`` in which reading a ``Series`` saved to an HDF file in 'fixed' format fails when an explicit ``mode='r'`` argument is supplied (:issue:`16583`)
5960

6061
Plotting
6162
^^^^^^^^

pandas/io/pytables.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -282,21 +282,24 @@ def to_hdf(path_or_buf, key, value, mode=None, complevel=None, complib=None,
282282
f(path_or_buf)
283283

284284

285-
def read_hdf(path_or_buf, key=None, **kwargs):
285+
def read_hdf(path_or_buf, key=None, mode='r', **kwargs):
286286
""" read from the store, close it if we opened it
287287
288288
Retrieve pandas object stored in file, optionally based on where
289289
criteria
290290
291291
Parameters
292292
----------
293-
path_or_buf : path (string), buffer, or path object (pathlib.Path or
294-
py._path.local.LocalPath) to read from
293+
path_or_buf : path (string), buffer or path object (pathlib.Path or
294+
py._path.local.LocalPath) designating the file to open, or an
295+
already opened pd.HDFStore object
295296
296297
.. versionadded:: 0.19.0 support for pathlib, py.path.
297298
298299
key : group identifier in the store. Can be omitted if the HDF file
299300
contains a single pandas object.
301+
mode : string, {'r', 'r+', 'a'}, default 'r'. Mode to use when opening
302+
the file. Ignored if path_or_buf is a pd.HDFStore.
300303
where : list of Term (or convertable) objects, optional
301304
start : optional, integer (defaults to None), row number to start
302305
selection
@@ -313,10 +316,9 @@ def read_hdf(path_or_buf, key=None, **kwargs):
313316
314317
"""
315318

316-
if kwargs.get('mode', 'a') not in ['r', 'r+', 'a']:
319+
if mode not in ['r', 'r+', 'a']:
317320
raise ValueError('mode {0} is not allowed while performing a read. '
318-
'Allowed modes are r, r+ and a.'
319-
.format(kwargs.get('mode')))
321+
'Allowed modes are r, r+ and a.'.format(mode))
320322
# grab the scope
321323
if 'where' in kwargs:
322324
kwargs['where'] = _ensure_term(kwargs['where'], scope_level=1)
@@ -335,6 +337,7 @@ def read_hdf(path_or_buf, key=None, **kwargs):
335337
raise compat.FileNotFoundError(
336338
'File %s does not exist' % path_or_buf)
337339

340+
store = HDFStore(path_or_buf, mode=mode, **kwargs)
338341
# can't auto open/close if we are using an iterator
339342
# so delegate to the iterator
340343
store = HDFStore(path_or_buf, **kwargs)

pandas/tests/io/test_pytables.py

+17
Original file line numberDiff line numberDiff line change
@@ -5190,6 +5190,23 @@ def test_query_compare_column_type(self):
51905190
expected = df.loc[[], :]
51915191
tm.assert_frame_equal(expected, result)
51925192

5193+
@pytest.mark.parametrize('format', ['fixed', 'table'])
5194+
def test_read_hdf_series_mode_r(self, format):
5195+
# GH 16583
5196+
# Tests that reading a Series saved to an HDF file
5197+
# still works if a mode='r' argument is supplied
5198+
series = tm.makeFloatSeries()
5199+
with ensure_clean_path(self.path) as path:
5200+
series.to_hdf(path, key='data', format=format)
5201+
result = pd.read_hdf(path, key='data', mode='r')
5202+
tm.assert_series_equal(result, series)
5203+
5204+
@pytest.mark.skipif(sys.version_info < (3, 6), reason="Need python 3.6")
5205+
def test_fspath(self):
5206+
with tm.ensure_clean('foo.h5') as path:
5207+
with pd.HDFStore(path) as store:
5208+
assert os.fspath(store) == str(path)
5209+
51935210

51945211
class TestHDFComplexValues(Base):
51955212
# GH10447

0 commit comments

Comments
 (0)