Skip to content

Commit

Permalink
DEPR: xlwt for writing excel files (#38317)
Browse files Browse the repository at this point in the history
  • Loading branch information
rhshadrach committed Dec 8, 2020
1 parent da237dd commit 37f7bdc
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 7 deletions.
7 changes: 7 additions & 0 deletions doc/source/user_guide/io.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3200,6 +3200,13 @@ pandas supports writing Excel files to buffer-like objects such as ``StringIO``
Excel writer engines
''''''''''''''''''''

.. deprecated:: 1.2.0

As the `xlwt <https://pypi.org/project/xlwt/>`__ package is no longer
maintained, the ``xlwt`` engine will be removed from a future version
of pandas. This is the only engine in pandas that supports writing to
``.xls`` files.

pandas chooses an Excel writer via two methods:

1. the ``engine`` keyword argument
Expand Down
10 changes: 10 additions & 0 deletions doc/source/user_guide/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,16 @@ display.html.use_mathjax True When True, Jupyter notebook
dollar symbol.
io.excel.xls.writer xlwt The default Excel writer engine for
'xls' files.

.. deprecated:: 1.2.0

As `xlwt <https://pypi.org/project/xlwt/>`__
package is no longer maintained, the ``xlwt``
engine will be removed in a future version of
pandas. Since this is the only engine in pandas
that supports writing to ``.xls`` files,
this option will also be removed.

io.excel.xlsm.writer openpyxl The default Excel writer engine for
'xlsm' files. Available options:
'openpyxl' (the default).
Expand Down
25 changes: 20 additions & 5 deletions doc/source/whatsnew/v1.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,27 @@ including other versions of pandas.

.. warning::

The packages `xlrd <https://xlrd.readthedocs.io/en/latest/>`_ for reading excel
files and `xlwt <https://xlwt.readthedocs.io/en/latest/>`_ for
writing excel files are no longer maintained. These are the only engines in pandas
that support the xls format.

Previously, the default argument ``engine=None`` to ``pd.read_excel``
would result in using the `xlrd <https://xlrd.readthedocs.io/en/latest/>`_ engine in
many cases. The engine ``xlrd`` is no longer maintained, and is not supported with
python >= 3.9. If `openpyxl <https://pypi.org/project/openpyxl/>`_ is installed,
many of these cases will now default to using the ``openpyxl`` engine. See the
:func:`read_excel` documentation for more details.
would result in using the ``xlrd`` engine in many cases. If
`openpyxl <https://openpyxl.readthedocs.io/en/stable/>`_ is installed,
many of these cases will now default to using the ``openpyxl`` engine.
See the :func:`read_excel` documentation for more details. Attempting to read
``.xls`` files or specifying ``engine="xlrd"`` to ``pd.read_excel`` will not
raise a warning. However users should be aware that ``xlrd`` is already
broken with certain package configurations, for example with Python 3.9
when `defusedxml <https://github.com/tiran/defusedxml/>`_ is installed, and
is anticipated to be unusable in the future.

Attempting to use the the ``xlwt`` engine will raise a ``FutureWarning``
unless the option :attr:`io.excel.xls.writer` is set to ``"xlwt"``.
While this option is now deprecated and will also raise a ``FutureWarning``,
it can be globally set and the warning suppressed. Users are recommended to
write ``.xlsx`` files using the ``openpyxl`` engine instead.

.. ---------------------------------------------------------------------------
Expand Down
7 changes: 7 additions & 0 deletions pandas/core/config_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,13 @@ def use_inf_as_na_cb(key):
writer_engine_doc.format(ext="xls", others=", ".join(_xls_options)),
validator=str,
)
cf.deprecate_option(
"io.excel.xls.writer",
msg="As the xlwt package is no longer maintained, the xlwt engine will be "
"removed in a future version of pandas. This is the only engine in pandas that "
"supports writing in the xls format. Install openpyxl and write to an "
"xlsx file instead.",
)

with cf.config_prefix("io.excel.xlsm"):
cf.register_option(
Expand Down
7 changes: 7 additions & 0 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2093,6 +2093,13 @@ def to_excel(
Write engine to use, 'openpyxl' or 'xlsxwriter'. You can also set this
via the options ``io.excel.xlsx.writer``, ``io.excel.xls.writer``, and
``io.excel.xlsm.writer``.
.. deprecated:: 1.2.0
As the `xlwt <https://pypi.org/project/xlwt/>`__ package is no longer
maintained, the ``xlwt`` engine will be removed in a future version
of pandas.
merge_cells : bool, default True
Write MultiIndex and Hierarchical Rows as merged cells.
encoding : str, optional
Expand Down
29 changes: 28 additions & 1 deletion pandas/io/excel/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,13 @@ class ExcelWriter(metaclass=abc.ABCMeta):
Engine to use for writing. If None, defaults to
``io.excel.<extension>.writer``. NOTE: can only be passed as a keyword
argument.
.. deprecated:: 1.2.0
As the `xlwt <https://pypi.org/project/xlwt/>`__ package is no longer
maintained, the ``xlwt`` engine will be removed in a future
version of pandas.
date_format : str, default None
Format string for dates written into Excel files (e.g. 'YYYY-MM-DD').
datetime_format : str, default None
Expand Down Expand Up @@ -691,11 +698,31 @@ def __new__(cls, path, engine=None, **kwargs):
ext = "xlsx"

try:
engine = config.get_option(f"io.excel.{ext}.writer")
engine = config.get_option(f"io.excel.{ext}.writer", silent=True)
if engine == "auto":
engine = get_default_writer(ext)
except KeyError as err:
raise ValueError(f"No engine for filetype: '{ext}'") from err

if engine == "xlwt":
xls_config_engine = config.get_option(
"io.excel.xls.writer", silent=True
)
# Don't warn a 2nd time if user has changed the default engine for xls
if xls_config_engine != "xlwt":
warnings.warn(
"As the xlwt package is no longer maintained, the xlwt "
"engine will be removed in a future version of pandas. "
"This is the only engine in pandas that supports writing "
"in the xls format. Install openpyxl and write to an xlsx "
"file instead. You can set the option io.excel.xls.writer "
"to 'xlwt' to silence this warning. While this option is "
"deprecated and will also raise a warning, it can "
"be globally set and the warning suppressed.",
FutureWarning,
stacklevel=4,
)

cls = get_writer(engine)

return object.__new__(cls)
Expand Down
7 changes: 7 additions & 0 deletions pandas/io/formats/excel.py
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,13 @@ def write(
write engine to use if writer is a path - you can also set this
via the options ``io.excel.xlsx.writer``, ``io.excel.xls.writer``,
and ``io.excel.xlsm.writer``.
.. deprecated:: 1.2.0
As the `xlwt <https://pypi.org/project/xlwt/>`__ package is no longer
maintained, the ``xlwt`` engine will be removed in a future
version of pandas.
{storage_options}
.. versionadded:: 1.2.0
Expand Down
4 changes: 4 additions & 0 deletions pandas/tests/io/excel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@
pytest.mark.filterwarnings(
"ignore:This method will be removed in future versions:DeprecationWarning"
),
# GH 26552
pytest.mark.filterwarnings(
"ignore:As the xlwt package is no longer maintained:FutureWarning"
),
]
23 changes: 22 additions & 1 deletion pandas/tests/io/excel/test_xlwt.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import numpy as np
import pytest

from pandas import DataFrame, MultiIndex
from pandas import DataFrame, MultiIndex, options
import pandas._testing as tm

from pandas.io.excel import ExcelWriter, _XlwtWriter
Expand Down Expand Up @@ -69,3 +69,24 @@ def test_write_append_mode_raises(ext):
with tm.ensure_clean(ext) as f:
with pytest.raises(ValueError, match=msg):
ExcelWriter(f, engine="xlwt", mode="a")


def test_to_excel_xlwt_warning(ext):
# GH 26552
df = DataFrame(np.random.randn(3, 10))
with tm.ensure_clean(ext) as path:
with tm.assert_produces_warning(
FutureWarning,
match="As the xlwt package is no longer maintained",
):
df.to_excel(path)


def test_option_xls_writer_deprecated(ext):
# GH 26552
with tm.assert_produces_warning(
FutureWarning,
match="As the xlwt package is no longer maintained",
check_stacklevel=False,
):
options.io.excel.xls.writer = "xlwt"

0 comments on commit 37f7bdc

Please sign in to comment.