diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index ab242ece98181..a8e3ee8042b0f 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -1094,6 +1094,7 @@ I/O - Bug while selecting from :class:`HDFStore` with ``where=''`` specified (:issue:`26610`). - Fixed bug in :func:`DataFrame.to_excel()` where custom objects (i.e. `PeriodIndex`) inside merged cells were not being converted into types safe for the Excel writer (:issue:`27006`) - Bug in :meth:`read_hdf` where reading a timezone aware :class:`DatetimeIndex` would raise a ``TypeError`` (:issue:`11926`) +- Bug in :meth:`to_msgpack` and :meth:`read_msgpack` which would raise a ``ValueError`` rather than a ``FileNotFoundError`` for an invalid path (:issue:`27160`) Plotting ^^^^^^^^ diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 4e9f74162ae78..ec89208e3bbb8 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2560,7 +2560,7 @@ def to_msgpack(self, path_or_buf=None, encoding="utf-8", **kwargs): Parameters ---------- path : string File path, buffer-like, or None - if None, return generated string + if None, return generated bytes append : bool whether to append to an existing msgpack (default is False) compress : type of compressor (zlib or blosc), default to None (no @@ -2568,9 +2568,9 @@ def to_msgpack(self, path_or_buf=None, encoding="utf-8", **kwargs): Returns ------- - None or str + None or bytes If path_or_buf is None, returns the resulting msgpack format as a - string. Otherwise returns None. + byte string. Otherwise returns None. """ from pandas.io import packers diff --git a/pandas/io/packers.py b/pandas/io/packers.py index b0ce7a4ccb12a..2e411fb07885f 100644 --- a/pandas/io/packers.py +++ b/pandas/io/packers.py @@ -108,7 +108,7 @@ def to_msgpack(path_or_buf, *args, **kwargs): Parameters ---------- path_or_buf : string File path, buffer-like, or None - if None, return generated string + if None, return generated bytes args : an object or objects to serialize encoding : encoding for unicode objects append : boolean whether to append to an existing msgpack @@ -139,8 +139,12 @@ def writer(fh): path_or_buf = _stringify_path(path_or_buf) if isinstance(path_or_buf, str): - with open(path_or_buf, mode) as fh: - writer(fh) + try: + with open(path_or_buf, mode) as fh: + writer(fh) + except FileNotFoundError: + msg = "File b'{}' does not exist".format(path_or_buf) + raise FileNotFoundError(msg) elif path_or_buf is None: buf = BytesIO() writer(buf) @@ -204,13 +208,11 @@ def read(fh): # see if we have an actual file if isinstance(path_or_buf, str): try: - exists = os.path.exists(path_or_buf) - except (TypeError, ValueError): - exists = False - - if exists: with open(path_or_buf, "rb") as fh: return read(fh) + except FileNotFoundError: + msg = "File b'{}' does not exist".format(path_or_buf) + raise FileNotFoundError(msg) if isinstance(path_or_buf, bytes): # treat as a binary-like diff --git a/pandas/tests/io/test_common.py b/pandas/tests/io/test_common.py index 426698bfa1e94..8e09e96fbd471 100644 --- a/pandas/tests/io/test_common.py +++ b/pandas/tests/io/test_common.py @@ -142,7 +142,7 @@ def test_iterator(self): (pd.read_stata, "os", FileNotFoundError, "dta"), (pd.read_sas, "os", FileNotFoundError, "sas7bdat"), (pd.read_json, "os", ValueError, "json"), - (pd.read_msgpack, "os", ValueError, "mp"), + (pd.read_msgpack, "os", FileNotFoundError, "mp"), (pd.read_pickle, "os", FileNotFoundError, "pickle"), ], ) @@ -177,7 +177,7 @@ def test_read_non_existant(self, reader, module, error_class, fn_ext): (pd.read_stata, "os", FileNotFoundError, "dta"), (pd.read_sas, "os", FileNotFoundError, "sas7bdat"), (pd.read_json, "os", ValueError, "json"), - (pd.read_msgpack, "os", ValueError, "mp"), + (pd.read_msgpack, "os", FileNotFoundError, "mp"), (pd.read_pickle, "os", FileNotFoundError, "pickle"), ], ) diff --git a/pandas/tests/io/test_packers.py b/pandas/tests/io/test_packers.py index 83c11cd9ab996..fb1f657905be7 100644 --- a/pandas/tests/io/test_packers.py +++ b/pandas/tests/io/test_packers.py @@ -165,12 +165,15 @@ def __init__(self): self.read = 0 msg = "Invalid file path or buffer object type: " + invalid_path = os.path.join("nonexistent_dir", "df.msgpack") with pytest.raises(ValueError, match=msg.format("NoneType")): read_msgpack(path_or_buf=None) with pytest.raises(ValueError, match=msg.format("dict")): read_msgpack(path_or_buf={}) with pytest.raises(ValueError, match=msg.format(r".*\.A")): read_msgpack(path_or_buf=A()) + with pytest.raises(FileNotFoundError, match="does not exist"): + read_msgpack(path_or_buf=invalid_path) @pytest.mark.filterwarnings("ignore:.*msgpack:FutureWarning")