An undocumented argument in Python’s locale.atof function
Created
Modified
Published
Suppose we have a string like this:
>>> mystr = '1,200.30'
and we want to parse it into a number, following the locale rules for the meaning of periods and commas. Well, one option is to use the locale package to turn it into a float.
>>> import locale
>>> locale.setlocale(locale.LC_NUMERIC, '')
'en_US.UTF-8'
>>> locale.atof('1,200.30')
1200.3
However, if these numbers represent currency, we don’t want a float, we want a Decimal. But how do we get it? We can’t use the string directly:
>>> decimal.Decimal('1,200.30')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>]
and if we try to convert it to a float first, we get rounding error:
>>> import decimal
>>> decimal.Decimal(locale.atof('1,200.30'))
Decimal('1200.299999999999954525264911353588104248046875')
It turns out, though, that locale.atof takes a func parameter. Here it is in Python 3:
def atof(string, func=float):
"Parses a string as a float according to the locale settings."
return func(delocalize(string))
and here it is in Python 2:
def atof(string, func=float):
"Parses a string as a float according to the locale settings."
#First, get rid of the grouping
ts = localeconv()['thousands_sep']
if ts:
string = string.replace(ts, '')
#next, replace the decimal point with a dot
dd = localeconv()['decimal_point']
if dd:
string = string.replace(dd, '.')
#finally, parse the string
return func(string)
So we can just do this:
>>> locale.setlocale(locale.LC_NUMERIC, '')
'en_US.UTF-8'
>>> locale.atof('1,200.30', func=decimal.Decimal)
Decimal('1200.30')
It’s not in the official documentation, though.
locale.atof( string )
Converts a string to a floating point number, following the LC_NUMERIC settings.
https://docs.python.org/3/library/locale.html#locale.atof
This undocumented parameter is well-known, but even after Python 3 it does not seem to be documented yet.
Notice the undocumented argument for the result type:
>>> locale.atof('1,234', decimal.Decimal) Decimal('1234') >>> locale.atof('1,234', fractions.Fraction) Fraction(1234, 1)I’d advise writing your own function instead of relying on an undocumented argument.
—eryksun, June 26, 2013
https://mail.python.org/pipermail/tutor/2013-June/096421.html
I’m not sure I agree with that. I think it might be better to try to persuade the Python maintainers to document this excellent little feature.
Addendum 2026-01-23: it’s documented now.
locale.atof( string, func=float )
Converts a string to a number, following the LC_NUMERIC settings, by calling func on the result of calling delocalize() on string.
https://docs.python.org/3/library/locale.html#locale.atof
The commit pull request commit was from May 27, 2020, and the commit that added to the repo was April 2, 2022.
https://github.com/python/cpython/commit/208da6d508bb2683732151f4ae288dfc8001267c
https://github.com/python/cpython/pull/18183/commits/b61a38e81f132e01b19ee1c5086f678e0172234e