Skip to content

Commit 37f7bdc

Browse files
authored
DEPR: xlwt for writing excel files (#38317)
1 parent da237dd commit 37f7bdc

File tree

9 files changed

+112
-7
lines changed

9 files changed

+112
-7
lines changed

doc/source/user_guide/io.rst

+7
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,13 @@ pandas supports writing Excel files to buffer-like objects such as ``StringIO``
32003200
Excel writer engines
32013201
''''''''''''''''''''
32023202

3203+
.. deprecated:: 1.2.0
3204+
3205+
As the `xlwt <https://pypi.org/project/xlwt/>`__ package is no longer
3206+
maintained, the ``xlwt`` engine will be removed from a future version
3207+
of pandas. This is the only engine in pandas that supports writing to
3208+
``.xls`` files.
3209+
32033210
pandas chooses an Excel writer via two methods:
32043211

32053212
1. the ``engine`` keyword argument

doc/source/user_guide/options.rst

+10
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,16 @@ display.html.use_mathjax True When True, Jupyter notebook
432432
dollar symbol.
433433
io.excel.xls.writer xlwt The default Excel writer engine for
434434
'xls' files.
435+
436+
.. deprecated:: 1.2.0
437+
438+
As `xlwt <https://pypi.org/project/xlwt/>`__
439+
package is no longer maintained, the ``xlwt``
440+
engine will be removed in a future version of
441+
pandas. Since this is the only engine in pandas
442+
that supports writing to ``.xls`` files,
443+
this option will also be removed.
444+
435445
io.excel.xlsm.writer openpyxl The default Excel writer engine for
436446
'xlsm' files. Available options:
437447
'openpyxl' (the default).

doc/source/whatsnew/v1.2.0.rst

+20-5
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,27 @@ including other versions of pandas.
1010

1111
.. warning::
1212

13+
The packages `xlrd <https://xlrd.readthedocs.io/en/latest/>`_ for reading excel
14+
files and `xlwt <https://xlwt.readthedocs.io/en/latest/>`_ for
15+
writing excel files are no longer maintained. These are the only engines in pandas
16+
that support the xls format.
17+
1318
Previously, the default argument ``engine=None`` to ``pd.read_excel``
14-
would result in using the `xlrd <https://xlrd.readthedocs.io/en/latest/>`_ engine in
15-
many cases. The engine ``xlrd`` is no longer maintained, and is not supported with
16-
python >= 3.9. If `openpyxl <https://pypi.org/project/openpyxl/>`_ is installed,
17-
many of these cases will now default to using the ``openpyxl`` engine. See the
18-
:func:`read_excel` documentation for more details.
19+
would result in using the ``xlrd`` engine in many cases. If
20+
`openpyxl <https://openpyxl.readthedocs.io/en/stable/>`_ is installed,
21+
many of these cases will now default to using the ``openpyxl`` engine.
22+
See the :func:`read_excel` documentation for more details. Attempting to read
23+
``.xls`` files or specifying ``engine="xlrd"`` to ``pd.read_excel`` will not
24+
raise a warning. However users should be aware that ``xlrd`` is already
25+
broken with certain package configurations, for example with Python 3.9
26+
when `defusedxml <https://github.com/tiran/defusedxml/>`_ is installed, and
27+
is anticipated to be unusable in the future.
28+
29+
Attempting to use the the ``xlwt`` engine will raise a ``FutureWarning``
30+
unless the option :attr:`io.excel.xls.writer` is set to ``"xlwt"``.
31+
While this option is now deprecated and will also raise a ``FutureWarning``,
32+
it can be globally set and the warning suppressed. Users are recommended to
33+
write ``.xlsx`` files using the ``openpyxl`` engine instead.
1934

2035
.. ---------------------------------------------------------------------------
2136

pandas/core/config_init.py

+7
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,13 @@ def use_inf_as_na_cb(key):
581581
writer_engine_doc.format(ext="xls", others=", ".join(_xls_options)),
582582
validator=str,
583583
)
584+
cf.deprecate_option(
585+
"io.excel.xls.writer",
586+
msg="As the xlwt package is no longer maintained, the xlwt engine will be "
587+
"removed in a future version of pandas. This is the only engine in pandas that "
588+
"supports writing in the xls format. Install openpyxl and write to an "
589+
"xlsx file instead.",
590+
)
584591

585592
with cf.config_prefix("io.excel.xlsm"):
586593
cf.register_option(

pandas/core/generic.py

+7
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,13 @@ def to_excel(
20932093
Write engine to use, 'openpyxl' or 'xlsxwriter'. You can also set this
20942094
via the options ``io.excel.xlsx.writer``, ``io.excel.xls.writer``, and
20952095
``io.excel.xlsm.writer``.
2096+
2097+
.. deprecated:: 1.2.0
2098+
2099+
As the `xlwt <https://pypi.org/project/xlwt/>`__ package is no longer
2100+
maintained, the ``xlwt`` engine will be removed in a future version
2101+
of pandas.
2102+
20962103
merge_cells : bool, default True
20972104
Write MultiIndex and Hierarchical Rows as merged cells.
20982105
encoding : str, optional

pandas/io/excel/_base.py

+28-1
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,13 @@ class ExcelWriter(metaclass=abc.ABCMeta):
587587
Engine to use for writing. If None, defaults to
588588
``io.excel.<extension>.writer``. NOTE: can only be passed as a keyword
589589
argument.
590+
591+
.. deprecated:: 1.2.0
592+
593+
As the `xlwt <https://pypi.org/project/xlwt/>`__ package is no longer
594+
maintained, the ``xlwt`` engine will be removed in a future
595+
version of pandas.
596+
590597
date_format : str, default None
591598
Format string for dates written into Excel files (e.g. 'YYYY-MM-DD').
592599
datetime_format : str, default None
@@ -691,11 +698,31 @@ def __new__(cls, path, engine=None, **kwargs):
691698
ext = "xlsx"
692699

693700
try:
694-
engine = config.get_option(f"io.excel.{ext}.writer")
701+
engine = config.get_option(f"io.excel.{ext}.writer", silent=True)
695702
if engine == "auto":
696703
engine = get_default_writer(ext)
697704
except KeyError as err:
698705
raise ValueError(f"No engine for filetype: '{ext}'") from err
706+
707+
if engine == "xlwt":
708+
xls_config_engine = config.get_option(
709+
"io.excel.xls.writer", silent=True
710+
)
711+
# Don't warn a 2nd time if user has changed the default engine for xls
712+
if xls_config_engine != "xlwt":
713+
warnings.warn(
714+
"As the xlwt package is no longer maintained, the xlwt "
715+
"engine will be removed in a future version of pandas. "
716+
"This is the only engine in pandas that supports writing "
717+
"in the xls format. Install openpyxl and write to an xlsx "
718+
"file instead. You can set the option io.excel.xls.writer "
719+
"to 'xlwt' to silence this warning. While this option is "
720+
"deprecated and will also raise a warning, it can "
721+
"be globally set and the warning suppressed.",
722+
FutureWarning,
723+
stacklevel=4,
724+
)
725+
699726
cls = get_writer(engine)
700727

701728
return object.__new__(cls)

pandas/io/formats/excel.py

+7
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,13 @@ def write(
805805
write engine to use if writer is a path - you can also set this
806806
via the options ``io.excel.xlsx.writer``, ``io.excel.xls.writer``,
807807
and ``io.excel.xlsm.writer``.
808+
809+
.. deprecated:: 1.2.0
810+
811+
As the `xlwt <https://pypi.org/project/xlwt/>`__ package is no longer
812+
maintained, the ``xlwt`` engine will be removed in a future
813+
version of pandas.
814+
808815
{storage_options}
809816
810817
.. versionadded:: 1.2.0

pandas/tests/io/excel/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@
99
pytest.mark.filterwarnings(
1010
"ignore:This method will be removed in future versions:DeprecationWarning"
1111
),
12+
# GH 26552
13+
pytest.mark.filterwarnings(
14+
"ignore:As the xlwt package is no longer maintained:FutureWarning"
15+
),
1216
]

pandas/tests/io/excel/test_xlwt.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import numpy as np
22
import pytest
33

4-
from pandas import DataFrame, MultiIndex
4+
from pandas import DataFrame, MultiIndex, options
55
import pandas._testing as tm
66

77
from pandas.io.excel import ExcelWriter, _XlwtWriter
@@ -69,3 +69,24 @@ def test_write_append_mode_raises(ext):
6969
with tm.ensure_clean(ext) as f:
7070
with pytest.raises(ValueError, match=msg):
7171
ExcelWriter(f, engine="xlwt", mode="a")
72+
73+
74+
def test_to_excel_xlwt_warning(ext):
75+
# GH 26552
76+
df = DataFrame(np.random.randn(3, 10))
77+
with tm.ensure_clean(ext) as path:
78+
with tm.assert_produces_warning(
79+
FutureWarning,
80+
match="As the xlwt package is no longer maintained",
81+
):
82+
df.to_excel(path)
83+
84+
85+
def test_option_xls_writer_deprecated(ext):
86+
# GH 26552
87+
with tm.assert_produces_warning(
88+
FutureWarning,
89+
match="As the xlwt package is no longer maintained",
90+
check_stacklevel=False,
91+
):
92+
options.io.excel.xls.writer = "xlwt"

0 commit comments

Comments
 (0)