diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index dced7fd78649..d559ad5820d6 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -1032,7 +1032,13 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='', if len(fmt) != ncol: raise AttributeError('fmt has wrong shape. %s' % str(fmt)) format = asstr(delimiter).join(map(asstr, fmt)) - elif isinstance(fmt, str): + elif isinstance(fmt, basestring): + if isinstance(fmt, unicode): + try: + fmt = fmt.encode('ascii') + except UnicodeEncodeError: + raise ValueError('invalid unicode in fmt: %r' % (fmt,)) + n_fmt_chars = fmt.count('%') error = ValueError('fmt has wrong number of %% formats: %s' % fmt) if n_fmt_chars == 1: diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py index 66310a509c43..1fff6adcfd89 100644 --- a/numpy/lib/tests/test_io.py +++ b/numpy/lib/tests/test_io.py @@ -15,7 +15,7 @@ import numpy.ma as ma from numpy.lib._iotools import (ConverterError, ConverterLockError, ConversionWarning) -from numpy.compat import asbytes, asbytes_nested, bytes, asstr +from numpy.compat import asbytes, asbytes_nested, bytes, asstr, sixu from nose import SkipTest from numpy.ma.testutils import (TestCase, assert_equal, assert_array_equal, assert_raises, run_module_suite) @@ -330,6 +330,19 @@ def test_format(self): # Bad fmt, should raise a ValueError c = BytesIO() assert_raises(ValueError, np.savetxt, c, a, fmt=99) + + # Unicode fmt is casted if possible + c1 = BytesIO() + c2 = BytesIO() + np.savetxt(c1, a, fmt='%02d : %3.1f') + np.savetxt(c2, a, fmt=sixu('%02d : %3.1f')) + c1.seek(0) + c2.seek(0) + assert_equal(c1.readlines(), c2.readlines()) + + # ... but raises an error if not. + c = BytesIO() + assert_raises(ValueError, np.savetxt(c, a, fmt=sixu('\xe7'))) def test_header_footer(self): """