Skip to content

Commit b89f02d

Browse files
committed
Merge pull request #5446 from jtratner/default-imports-for-excel-writers
PERF/ENH: Use xlsxwriter by default (and then fall back on openpyxl).
2 parents 72a0c43 + e4b352c commit b89f02d

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
@@ -300,8 +300,7 @@ def use_inf_as_null_cb(key):
300300
with cf.config_prefix('io.excel'):
301301
# going forward, will be additional writers
302302
for ext, options in [('xls', ['xlwt']),
303-
('xlsm', ['openpyxl']),
304-
('xlsx', ['openpyxl'])]:
303+
('xlsm', ['openpyxl'])]:
305304
default = options.pop(0)
306305
if options:
307306
options = " " + ", ".join(options)
@@ -310,3 +309,17 @@ def use_inf_as_null_cb(key):
310309
doc = writer_engine_doc.format(ext=ext, default=default,
311310
others=options)
312311
cf.register_option(ext + '.writer', default, doc, validator=str)
312+
def _register_xlsx(engine, other):
313+
cf.register_option('xlsx.writer', engine,
314+
writer_engine_doc.format(ext='xlsx',
315+
default=engine,
316+
others=", '%s'" % other),
317+
validator=str)
318+
319+
try:
320+
# better memory footprint
321+
import xlsxwriter
322+
_register_xlsx('xlsxwriter', 'openpyxl')
323+
except ImportError:
324+
# fallback
325+
_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
@@ -1040,9 +1040,14 @@ def test_ExcelWriter_dispatch(self):
10401040
with tm.assertRaisesRegexp(ValueError, 'No engine'):
10411041
ExcelWriter('nothing')
10421042

1043-
_skip_if_no_openpyxl()
1043+
try:
1044+
import xlsxwriter
1045+
writer_klass = _XlsxWriter
1046+
except ImportError:
1047+
_skip_if_no_openpyxl()
1048+
writer_klass = _OpenpyxlWriter
10441049
writer = ExcelWriter('apple.xlsx')
1045-
tm.assert_isinstance(writer, _OpenpyxlWriter)
1050+
tm.assert_isinstance(writer, writer_klass)
10461051

10471052
_skip_if_no_xlwt()
10481053
writer = ExcelWriter('apple.xls')

0 commit comments

Comments
 (0)