diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index 920919755dc23..e1b99bfcbaaf6 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -68,7 +68,8 @@ Backwards incompatible API changes Deprecations ~~~~~~~~~~~~ - +- :func:`read_excel` engine argument "xlrd" will no longer be the default engine and + will be replaced by "openpyxl" in a future version (:issue:`28547`). - - diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 2a91381b7fbeb..ee0fb1ae19eb3 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -3,6 +3,7 @@ from io import BytesIO import os from textwrap import fill +import warnings from pandas._config import config @@ -781,7 +782,7 @@ def close(self): class ExcelFile: """ Class for parsing tabular excel sheets into DataFrame objects. - Uses xlrd. See read_excel for more documentation + Uses xlrd, openpyxl or odf. See read_excel for more documentation Parameters ---------- @@ -809,6 +810,11 @@ class ExcelFile: def __init__(self, io, engine=None): if engine is None: engine = "xlrd" + warnings.warn( + 'The Excel reader engine will default to "openpyxl" in the future. \ + Specify engine="openpyxl" to suppress this warning.', + FutureWarning, + ) if engine not in self._engines: raise ValueError(f"Unknown engine: {engine}") diff --git a/pandas/tests/io/excel/test_xlrd.py b/pandas/tests/io/excel/test_xlrd.py index cc7e2311f362a..3e8d300f65c35 100644 --- a/pandas/tests/io/excel/test_xlrd.py +++ b/pandas/tests/io/excel/test_xlrd.py @@ -1,3 +1,5 @@ +import warnings + import pytest import pandas as pd @@ -26,7 +28,6 @@ def test_read_xlrd_book(read_ext, frame): with tm.ensure_clean(read_ext) as pth: df.to_excel(pth, sheet_name) book = xlrd.open_workbook(pth) - with ExcelFile(book, engine=engine) as xl: result = pd.read_excel(xl, sheet_name, index_col=0) tm.assert_frame_equal(df, result) @@ -38,6 +39,24 @@ def test_read_xlrd_book(read_ext, frame): # TODO: test for openpyxl as well def test_excel_table_sheet_by_index(datapath, read_ext): path = datapath("io", "data", "excel", "test1{}".format(read_ext)) - with pd.ExcelFile(path) as excel: - with pytest.raises(xlrd.XLRDError): - pd.read_excel(excel, "asdf") + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + with pd.ExcelFile(path) as excel: + with pytest.raises(xlrd.XLRDError): + pd.read_excel(excel, "asdf") + + +# See issue #29375 +def test_excel_file_warning_with_default_engine(datapath): + path = datapath("io", "data", "excel", "test1.xls") + with warnings.catch_warnings(record=True) as w: + pd.ExcelFile(path) + assert "default to \"openpyxl\" in the future." in str(w[-1].message) + + +# See issue #29375 +def test_read_excel_warning_with_default_engine(tmpdir, datapath): + path = datapath("io", "data", "excel", "test1.xls") + with warnings.catch_warnings(record=True) as w: + pd.read_excel(path, "Sheet1") + assert "default to \"openpyxl\" in the future." in str(w[-1].message)