Skip to content

Commit e4b352c

Browse files
committed
PERF: Use xlsxwriter by default (if available)
1 parent b139288 commit e4b352c

File tree

3 files changed

+39
-14
lines changed

3 files changed

+39
-14
lines changed

doc/source/io.rst

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,8 +1825,10 @@ written. For example:
18251825
18261826
df.to_excel('path_to_file.xlsx', sheet_name='Sheet1')
18271827
1828-
Files with a ``.xls`` extension will be written using ``xlwt`` and those with
1829-
a ``.xlsx`` extension will be written using ``openpyxl``.
1828+
Files with a ``.xls`` extension will be written using ``xlwt`` and those with a
1829+
``.xlsx`` extension will be written using ``xlsxwriter`` (if available) or
1830+
``openpyxl``.
1831+
18301832
The Panel class also has a ``to_excel`` instance method,
18311833
which writes each DataFrame in the Panel to a separate sheet.
18321834

@@ -1858,14 +1860,19 @@ Excel writer engines
18581860
1. the ``engine`` keyword argument
18591861
2. the filename extension (via the default specified in config options)
18601862

1861-
By default, ``pandas`` uses `openpyxl <http://packages.python.org/openpyxl/>`__
1862-
for ``.xlsx`` and ``.xlsm`` files and `xlwt <http://www.python-excel.org/>`__
1863-
for ``.xls`` files. If you have multiple engines installed, you can set the
1864-
default engine through :ref:`setting the config options <basics.working_with_options>`
1865-
``io.excel.xlsx.writer`` and ``io.excel.xls.writer``.
1863+
By default, ``pandas`` uses the `XlsxWriter`_ for ``.xlsx`` and `openpyxl`_
1864+
for ``.xlsm`` files and `xlwt`_ for ``.xls`` files. If you have multiple
1865+
engines installed, you can set the default engine through :ref:`setting the
1866+
config options <basics.working_with_options>` ``io.excel.xlsx.writer`` and
1867+
``io.excel.xls.writer``. pandas will fall back on `openpyxl`_ for ``.xlsx``
1868+
files if `Xlsxwriter`_ is not available.
1869+
1870+
.. _XlsxWriter: http://xlsxwriter.readthedocs.org
1871+
.. _openpyxl: http://packages.python.org/openpyxl/
1872+
.. _xlwt: http://www.python-excel.org
18661873

1867-
For example if the `XlsxWriter <http://xlsxwriter.readthedocs.org>`__
1868-
module is installed you can use it as a xlsx writer engine as follows:
1874+
To specify which writer you want to use, you can pass an engine keyword
1875+
argument to ``to_excel`` and to ``ExcelWriter``.
18691876

18701877
.. code-block:: python
18711878

pandas/core/config_init.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,7 @@ def use_inf_as_null_cb(key):
290290
with cf.config_prefix('io.excel'):
291291
# going forward, will be additional writers
292292
for ext, options in [('xls', ['xlwt']),
293-
('xlsm', ['openpyxl']),
294-
('xlsx', ['openpyxl'])]:
293+
('xlsm', ['openpyxl'])]:
295294
default = options.pop(0)
296295
if options:
297296
options = " " + ", ".join(options)
@@ -300,3 +299,17 @@ def use_inf_as_null_cb(key):
300299
doc = writer_engine_doc.format(ext=ext, default=default,
301300
others=options)
302301
cf.register_option(ext + '.writer', default, doc, validator=str)
302+
def _register_xlsx(engine, other):
303+
cf.register_option('xlsx.writer', engine,
304+
writer_engine_doc.format(ext='xlsx',
305+
default=engine,
306+
others=", '%s'" % other),
307+
validator=str)
308+
309+
try:
310+
# better memory footprint
311+
import xlsxwriter
312+
_register_xlsx('xlsxwriter', 'openpyxl')
313+
except ImportError:
314+
# fallback
315+
_register_xlsx('openpyxl', 'xlsxwriter')

pandas/io/tests/test_excel.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from pandas.io.parsers import read_csv
1515
from pandas.io.excel import (
1616
ExcelFile, ExcelWriter, read_excel, _XlwtWriter, _OpenpyxlWriter,
17-
register_writer
17+
register_writer, _XlsxWriter
1818
)
1919
from pandas.util.testing import ensure_clean
2020
from pandas.core.config import set_option, get_option
@@ -1026,9 +1026,14 @@ def test_ExcelWriter_dispatch(self):
10261026
with tm.assertRaisesRegexp(ValueError, 'No engine'):
10271027
ExcelWriter('nothing')
10281028

1029-
_skip_if_no_openpyxl()
1029+
try:
1030+
import xlsxwriter
1031+
writer_klass = _XlsxWriter
1032+
except ImportError:
1033+
_skip_if_no_openpyxl()
1034+
writer_klass = _OpenpyxlWriter
10301035
writer = ExcelWriter('apple.xlsx')
1031-
tm.assert_isinstance(writer, _OpenpyxlWriter)
1036+
tm.assert_isinstance(writer, writer_klass)
10321037

10331038
_skip_if_no_xlwt()
10341039
writer = ExcelWriter('apple.xls')

0 commit comments

Comments
 (0)