From 0f9537845444d28353a9a048a660d4d33e3e0a59 Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Sat, 26 Dec 2020 16:37:19 -0800 Subject: [PATCH 1/7] ENH: Add xlsb auto detection to read_excel and respect default options --- doc/source/whatsnew/v1.3.0.rst | 2 ++ pandas/io/excel/_base.py | 28 ++++++++++----------------- pandas/io/excel/_util.py | 26 +++++++++++++++---------- pandas/tests/io/excel/test_readers.py | 2 -- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index c7573ee860744..c0b9923b3d32b 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -45,6 +45,8 @@ Other enhancements - Improved consistency of error message when passing an invalid ``win_type`` argument in :class:`Window` (:issue:`15969`) - :func:`pandas.read_sql_query` now accepts a ``dtype`` argument to cast the columnar data from the SQL database based on user input (:issue:`10285`) - Improved integer type mapping from pandas to SQLAlchemy when using :meth:`DataFrame.to_sql` (:issue:`35076`) +- :func:`pandas.read_excel` can now auto detect .xlsb files (:issue:`35416`) +- :func:`pandas.read_excel` now respects ``pandas.set_option`` (:issue:`34242`) .. --------------------------------------------------------------------------- diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 221e8b9ccfb14..dd447b9a098a1 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -25,7 +25,7 @@ from pandas.io.common import IOHandles, get_handle, stringify_path, validate_header_arg from pandas.io.excel._util import ( fill_mi_header, - get_default_writer, + get_default_engine, get_writer, maybe_convert_usecols, pop_header_name, @@ -701,7 +701,7 @@ def __new__(cls, path, engine=None, **kwargs): try: engine = config.get_option(f"io.excel.{ext}.writer", silent=True) if engine == "auto": - engine = get_default_writer(ext) + engine = get_default_engine(ext, mode="write") except KeyError as err: raise ValueError(f"No engine for filetype: '{ext}'") from err @@ -1003,6 +1003,8 @@ class ExcelFile: then `odf `_ will be used. - Otherwise if ``path_or_buffer`` is an xls format, ``xlrd`` will be used. + - Otherwise if ``path_or_buffer`` is in xlsb format, + ``pyxlsb`` will be used. - Otherwise if `openpyxl `_ is installed, then ``openpyxl`` will be used. - Otherwise if ``xlrd >= 2.0`` is installed, a ``ValueError`` will be raised. @@ -1064,21 +1066,12 @@ def __init__( ) if engine is None: - if ext == "ods": - engine = "odf" - elif ext == "xls": - engine = "xlrd" - else: - # GH 35029 - Prefer openpyxl except for xls files - if ( - import_optional_dependency( - "openpyxl", raise_on_missing=False, on_version="ignore" - ) - is not None - ): - engine = "openpyxl" - else: - engine = "xlrd" + try: + engine = config.get_option(f"io.excel.{ext}.", silent=True) + if engine == "auto": + engine = get_default_engine(ext, mode="read") + except KeyError as err: + raise ValueError(f"No engine for filetype: '{ext}'") from err if engine == "xlrd" and ext != "xls" and xlrd_version is not None: if xlrd_version >= "2": @@ -1106,7 +1099,6 @@ def __init__( FutureWarning, stacklevel=stacklevel, ) - assert engine in self._engines, f"Engine {engine} not recognized" self.engine = engine self.storage_options = storage_options diff --git a/pandas/io/excel/_util.py b/pandas/io/excel/_util.py index 47105916a9c78..0525f68a50e9a 100644 --- a/pandas/io/excel/_util.py +++ b/pandas/io/excel/_util.py @@ -23,32 +23,38 @@ def register_writer(klass): _writers[engine_name] = klass -def get_default_writer(ext): +def get_default_engine(ext, mode="read"): """ - Return the default writer for the given extension. + Return the default reader/writer for the given extension. Parameters ---------- ext : str The excel file extension for which to get the default engine. + mode : str + Whether to get the default engine for reading or writing. + Either 'read' or 'write' Returns ------- str The default engine for the extension. """ - _default_writers = { + _default_engines = { "xlsx": "openpyxl", "xlsm": "openpyxl", - "xls": "xlwt", + "xlsb": "pyxlsb", + "xls": "xlrd", "ods": "odf", } - xlsxwriter = import_optional_dependency( - "xlsxwriter", raise_on_missing=False, on_version="warn" - ) - if xlsxwriter: - _default_writers["xlsx"] = "xlsxwriter" - return _default_writers[ext] + if mode == "write": + _default_engines["xls"] = "xlwt" + xlsxwriter = import_optional_dependency( + "xlsxwriter", raise_on_missing=False, on_version="warn" + ) + if xlsxwriter: + _default_engines["xlsx"] = "xlsxwriter" + return _default_engines[ext] def get_writer(engine_name): diff --git a/pandas/tests/io/excel/test_readers.py b/pandas/tests/io/excel/test_readers.py index df1250cee8b00..89ddfcabd49bf 100644 --- a/pandas/tests/io/excel/test_readers.py +++ b/pandas/tests/io/excel/test_readers.py @@ -1181,8 +1181,6 @@ def test_excel_read_binary(self, engine, read_ext): def test_excel_read_binary_via_read_excel(self, read_ext, engine): # GH 38424 - if read_ext == ".xlsb" and engine == "pyxlsb": - pytest.xfail("GH 38667 - should default to pyxlsb but doesn't") with open("test1" + read_ext, "rb") as f: result = pd.read_excel(f) expected = pd.read_excel("test1" + read_ext, engine=engine) From 7618ff856512cf31ea841a5d7e743f1d98df6760 Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Sat, 26 Dec 2020 17:12:22 -0800 Subject: [PATCH 2/7] Fix? --- pandas/io/excel/_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index dd447b9a098a1..8e73b9725dda7 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -1067,7 +1067,7 @@ def __init__( if engine is None: try: - engine = config.get_option(f"io.excel.{ext}.", silent=True) + engine = config.get_option(f"io.excel.{ext}.reader", silent=True) if engine == "auto": engine = get_default_engine(ext, mode="read") except KeyError as err: From 1ed6aa664678395bdce61c844b87619ceadf3a7e Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Sun, 27 Dec 2020 20:08:11 -0800 Subject: [PATCH 3/7] Address code review --- pandas/core/config_init.py | 10 +++++----- pandas/io/excel/_base.py | 10 ++++------ pandas/io/excel/_util.py | 16 ++++++++++++---- pandas/tests/io/excel/test_readers.py | 7 +++++++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 7d9664bd9f965..ad9faa5d2eef9 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -524,7 +524,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="xls", others=", ".join(_xls_options)), - validator=str, + validator=is_one_of_factory(_xls_options+["auto"]), ) with cf.config_prefix("io.excel.xlsm"): @@ -532,7 +532,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="xlsm", others=", ".join(_xlsm_options)), - validator=str, + validator=is_one_of_factory(_xlsm_options+["auto"]), ) @@ -541,7 +541,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="xlsx", others=", ".join(_xlsx_options)), - validator=str, + validator=is_one_of_factory(_xlsx_options+["auto"]), ) @@ -550,7 +550,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="ods", others=", ".join(_ods_options)), - validator=str, + validator=is_one_of_factory(_ods_options+["auto"]), ) with cf.config_prefix("io.excel.xlsb"): @@ -558,7 +558,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="xlsb", others=", ".join(_xlsb_options)), - validator=str, + validator=is_one_of_factory(_xlsb_options+["auto"]), ) # Set up the io.excel specific writer configuration. diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 8e73b9725dda7..77b1ca8637cf4 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -1066,12 +1066,10 @@ def __init__( ) if engine is None: - try: - engine = config.get_option(f"io.excel.{ext}.reader", silent=True) - if engine == "auto": - engine = get_default_engine(ext, mode="read") - except KeyError as err: - raise ValueError(f"No engine for filetype: '{ext}'") from err + # ext will always be valid, otherwise inspect_excel format would raise + engine = config.get_option(f"io.excel.{ext}.reader", silent=True) + if engine == "auto": + engine = get_default_engine(ext, mode="read") if engine == "xlrd" and ext != "xls" and xlrd_version is not None: if xlrd_version >= "2": diff --git a/pandas/io/excel/_util.py b/pandas/io/excel/_util.py index 0525f68a50e9a..46674959e12f0 100644 --- a/pandas/io/excel/_util.py +++ b/pandas/io/excel/_util.py @@ -40,21 +40,29 @@ def get_default_engine(ext, mode="read"): str The default engine for the extension. """ - _default_engines = { + _default_readers = { "xlsx": "openpyxl", "xlsm": "openpyxl", "xlsb": "pyxlsb", "xls": "xlrd", "ods": "odf", } + _default_writers = { + "xlsx": "openpyxl", + "xlsm": "openpyxl", + "xlsb": "pyxlsb", + "xls": "xlwt", + "ods": "odf" + } if mode == "write": - _default_engines["xls"] = "xlwt" xlsxwriter = import_optional_dependency( "xlsxwriter", raise_on_missing=False, on_version="warn" ) if xlsxwriter: - _default_engines["xlsx"] = "xlsxwriter" - return _default_engines[ext] + _default_writers["xlsx"] = "xlsxwriter" + return _default_writers[ext] + else: + return _default_readers[ext] def get_writer(engine_name): diff --git a/pandas/tests/io/excel/test_readers.py b/pandas/tests/io/excel/test_readers.py index 89ddfcabd49bf..95d5992db9ec9 100644 --- a/pandas/tests/io/excel/test_readers.py +++ b/pandas/tests/io/excel/test_readers.py @@ -1227,3 +1227,10 @@ def test_read_datetime_multiindex(self, engine, read_ext): expected = DataFrame([], columns=expected_column_index) tm.assert_frame_equal(expected, actual) + + def test_engine_invalid_option(self, read_ext): + # read_ext includes the '.' hence the weird formatting + engine = pd.get_option(f"io.excel{read_ext}.reader") + with pytest.raises(ValueError, match="Value must be one of *"): + pd.set_option(f"io.excel{read_ext}.reader", "abc") + pd.set_option(f"io.excel{read_ext}.reader", engine) From 245e9b707563c603cd65e717509bda5b07a83d3d Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Sun, 27 Dec 2020 20:29:47 -0800 Subject: [PATCH 4/7] Fix checks --- pandas/core/config_init.py | 10 +++++----- pandas/io/excel/_base.py | 6 ++++++ pandas/io/excel/_util.py | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index ad9faa5d2eef9..fba82ae499e90 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -524,7 +524,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="xls", others=", ".join(_xls_options)), - validator=is_one_of_factory(_xls_options+["auto"]), + validator=is_one_of_factory(_xls_options + ["auto"]), ) with cf.config_prefix("io.excel.xlsm"): @@ -532,7 +532,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="xlsm", others=", ".join(_xlsm_options)), - validator=is_one_of_factory(_xlsm_options+["auto"]), + validator=is_one_of_factory(_xlsm_options + ["auto"]), ) @@ -541,7 +541,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="xlsx", others=", ".join(_xlsx_options)), - validator=is_one_of_factory(_xlsx_options+["auto"]), + validator=is_one_of_factory(_xlsx_options + ["auto"]), ) @@ -550,7 +550,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="ods", others=", ".join(_ods_options)), - validator=is_one_of_factory(_ods_options+["auto"]), + validator=is_one_of_factory(_ods_options + ["auto"]), ) with cf.config_prefix("io.excel.xlsb"): @@ -558,7 +558,7 @@ def use_inf_as_na_cb(key): "reader", "auto", reader_engine_doc.format(ext="xlsb", others=", ".join(_xlsb_options)), - validator=is_one_of_factory(_xlsb_options+["auto"]), + validator=is_one_of_factory(_xlsb_options + ["auto"]), ) # Set up the io.excel specific writer configuration. diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 77b1ca8637cf4..0bf891cd701e3 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -123,6 +123,10 @@ then `odf `_ will be used. - Otherwise if ``path_or_buffer`` is an xls format, ``xlrd`` will be used. + - Otherwise if ``path_or_buffer`` is in xlsb format, + ``pyxlsb`` will be used. + + .. versionadded:: 1.3.0 - Otherwise if `openpyxl `_ is installed, then ``openpyxl`` will be used. - Otherwise if ``xlrd >= 2.0`` is installed, a ``ValueError`` will be raised. @@ -1005,6 +1009,8 @@ class ExcelFile: ``xlrd`` will be used. - Otherwise if ``path_or_buffer`` is in xlsb format, ``pyxlsb`` will be used. + + .. versionadded:: 1.3.0 - Otherwise if `openpyxl `_ is installed, then ``openpyxl`` will be used. - Otherwise if ``xlrd >= 2.0`` is installed, a ``ValueError`` will be raised. diff --git a/pandas/io/excel/_util.py b/pandas/io/excel/_util.py index 46674959e12f0..b4a014de20979 100644 --- a/pandas/io/excel/_util.py +++ b/pandas/io/excel/_util.py @@ -52,7 +52,7 @@ def get_default_engine(ext, mode="read"): "xlsm": "openpyxl", "xlsb": "pyxlsb", "xls": "xlwt", - "ods": "odf" + "ods": "odf", } if mode == "write": xlsxwriter = import_optional_dependency( From 3cba8606369ed31465e6a7f3818e63e85c683f26 Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Tue, 29 Dec 2020 11:08:11 -0800 Subject: [PATCH 5/7] Address code review --- doc/source/whatsnew/v1.3.0.rst | 2 +- pandas/io/excel/_base.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index c0b9923b3d32b..70e303e532724 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -46,7 +46,7 @@ Other enhancements - :func:`pandas.read_sql_query` now accepts a ``dtype`` argument to cast the columnar data from the SQL database based on user input (:issue:`10285`) - Improved integer type mapping from pandas to SQLAlchemy when using :meth:`DataFrame.to_sql` (:issue:`35076`) - :func:`pandas.read_excel` can now auto detect .xlsb files (:issue:`35416`) -- :func:`pandas.read_excel` now respects ``pandas.set_option`` (:issue:`34242`) +- :func:`pandas.read_excel` now respects ``pandas.set_option`` (:issue:`34252`) .. --------------------------------------------------------------------------- diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 0bf891cd701e3..47e0e385338d9 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -1072,7 +1072,15 @@ def __init__( ) if engine is None: - # ext will always be valid, otherwise inspect_excel format would raise + if ( + import_optional_dependency( + "openpyxl", raise_on_missing=False, on_version="warn" + ) + is None + and xlrd_version is not None + ): + config.set_option("io.excel.xlsx.reader", "xlrd") + # ext will always be valid, otherwise inspect_excel_format would raise engine = config.get_option(f"io.excel.{ext}.reader", silent=True) if engine == "auto": engine = get_default_engine(ext, mode="read") From f139032a1bfcda0baac73f23ceb2253092010944 Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Wed, 30 Dec 2020 17:32:32 -0800 Subject: [PATCH 6/7] Changes from code review --- doc/source/whatsnew/v1.3.0.rst | 2 +- pandas/io/excel/_base.py | 12 ++---------- pandas/io/excel/_util.py | 23 +++++++++++++++++++---- pandas/tests/io/excel/test_readers.py | 5 ++--- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 70e303e532724..8ddc012445195 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -46,7 +46,6 @@ Other enhancements - :func:`pandas.read_sql_query` now accepts a ``dtype`` argument to cast the columnar data from the SQL database based on user input (:issue:`10285`) - Improved integer type mapping from pandas to SQLAlchemy when using :meth:`DataFrame.to_sql` (:issue:`35076`) - :func:`pandas.read_excel` can now auto detect .xlsb files (:issue:`35416`) -- :func:`pandas.read_excel` now respects ``pandas.set_option`` (:issue:`34252`) .. --------------------------------------------------------------------------- @@ -255,6 +254,7 @@ I/O - Allow custom error values for parse_dates argument of :func:`read_sql`, :func:`read_sql_query` and :func:`read_sql_table` (:issue:`35185`) - Bug in :func:`to_hdf` raising ``KeyError`` when trying to apply for subclasses of ``DataFrame`` or ``Series`` (:issue:`33748`). +- :func:`pandas.read_excel` now respects ``pandas.set_option`` (:issue:`34252`) Period ^^^^^^ diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 47e0e385338d9..427c9161e813b 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -705,7 +705,7 @@ def __new__(cls, path, engine=None, **kwargs): try: engine = config.get_option(f"io.excel.{ext}.writer", silent=True) if engine == "auto": - engine = get_default_engine(ext, mode="write") + engine = get_default_engine(ext, mode="writer") except KeyError as err: raise ValueError(f"No engine for filetype: '{ext}'") from err @@ -1072,18 +1072,10 @@ def __init__( ) if engine is None: - if ( - import_optional_dependency( - "openpyxl", raise_on_missing=False, on_version="warn" - ) - is None - and xlrd_version is not None - ): - config.set_option("io.excel.xlsx.reader", "xlrd") # ext will always be valid, otherwise inspect_excel_format would raise engine = config.get_option(f"io.excel.{ext}.reader", silent=True) if engine == "auto": - engine = get_default_engine(ext, mode="read") + engine = get_default_engine(ext, mode="reader") if engine == "xlrd" and ext != "xls" and xlrd_version is not None: if xlrd_version >= "2": diff --git a/pandas/io/excel/_util.py b/pandas/io/excel/_util.py index b4a014de20979..aafef741d0b30 100644 --- a/pandas/io/excel/_util.py +++ b/pandas/io/excel/_util.py @@ -23,7 +23,7 @@ def register_writer(klass): _writers[engine_name] = klass -def get_default_engine(ext, mode="read"): +def get_default_engine(ext, mode="reader"): """ Return the default reader/writer for the given extension. @@ -31,9 +31,9 @@ def get_default_engine(ext, mode="read"): ---------- ext : str The excel file extension for which to get the default engine. - mode : str + mode : str {'reader', 'writer'} Whether to get the default engine for reading or writing. - Either 'read' or 'write' + Either 'reader' or 'writer' Returns ------- @@ -54,7 +54,9 @@ def get_default_engine(ext, mode="read"): "xls": "xlwt", "ods": "odf", } - if mode == "write": + assert mode in ["reader", "writer"] + if mode == "writer": + # Prefer xlsxwriter over openpyxl if installed xlsxwriter = import_optional_dependency( "xlsxwriter", raise_on_missing=False, on_version="warn" ) @@ -62,6 +64,19 @@ def get_default_engine(ext, mode="read"): _default_writers["xlsx"] = "xlsxwriter" return _default_writers[ext] else: + if ( + import_optional_dependency( + "openpyxl", raise_on_missing=False, on_version="warn" + ) + is None + and import_optional_dependency( + "xlrd", raise_on_missing=False, on_version="raise" + ) + is not None + ): + # if no openpyxl but xlrd installed, return xlrd + # the version is handled elsewhere + _default_readers["xlsx"] = "xlrd" return _default_readers[ext] diff --git a/pandas/tests/io/excel/test_readers.py b/pandas/tests/io/excel/test_readers.py index 95d5992db9ec9..1d6e3a5d950ea 100644 --- a/pandas/tests/io/excel/test_readers.py +++ b/pandas/tests/io/excel/test_readers.py @@ -1230,7 +1230,6 @@ def test_read_datetime_multiindex(self, engine, read_ext): def test_engine_invalid_option(self, read_ext): # read_ext includes the '.' hence the weird formatting - engine = pd.get_option(f"io.excel{read_ext}.reader") with pytest.raises(ValueError, match="Value must be one of *"): - pd.set_option(f"io.excel{read_ext}.reader", "abc") - pd.set_option(f"io.excel{read_ext}.reader", engine) + with pd.option_context(f"io.excel{read_ext}.reader", "abc"): + pass From 53a5f8a0d882e2cb484618dee722daf030863d5a Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Thu, 31 Dec 2020 15:31:17 -0800 Subject: [PATCH 7/7] Changes from code reveiw --- doc/source/whatsnew/v1.3.0.rst | 2 +- pandas/io/excel/_base.py | 2 +- pandas/io/excel/_util.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 06917ce17ba79..b6a2ee575ac25 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -267,7 +267,7 @@ I/O - Bug in :func:`to_hdf` raising ``KeyError`` when trying to apply for subclasses of ``DataFrame`` or ``Series`` (:issue:`33748`). - Bug in :func:`json_normalize` resulting in the first element of a generator object not being included in the returned ``DataFrame`` (:issue:`35923`) -- :func:`pandas.read_excel` now respects ``pandas.set_option`` (:issue:`34252`) +- :func:`pandas.read_excel` now respects :func:``pandas.set_option`` (:issue:`34252`) Period ^^^^^^ diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 2cf2f3cd8e6ae..c6aab7be1a2a3 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -1008,7 +1008,7 @@ class ExcelFile: - Otherwise if ``path_or_buffer`` is an xls format, ``xlrd`` will be used. - Otherwise if ``path_or_buffer`` is in xlsb format, - ``pyxlsb`` will be used. + `pyxlsb `_ will be used. .. versionadded:: 1.3.0 - Otherwise if `openpyxl `_ is installed, diff --git a/pandas/io/excel/_util.py b/pandas/io/excel/_util.py index aafef741d0b30..b5d0d1347f119 100644 --- a/pandas/io/excel/_util.py +++ b/pandas/io/excel/_util.py @@ -66,11 +66,11 @@ def get_default_engine(ext, mode="reader"): else: if ( import_optional_dependency( - "openpyxl", raise_on_missing=False, on_version="warn" + "openpyxl", raise_on_missing=False, on_version="ignore" ) is None and import_optional_dependency( - "xlrd", raise_on_missing=False, on_version="raise" + "xlrd", raise_on_missing=False, on_version="ignore" ) is not None ):