62mkv
62mkv

Reputation: 1522

locale.setlocale(LC_NUMERIC): how to make it work on Windows

I am under Win10. This is my tiny script:

import locale
locale.setlocale(locale.LC_NUMERIC,"rus")

print locale.localeconv()

fv = 2.5
print str(fv)

This prints out:

{'mon_decimal_point': '', 'int_frac_digits': 127, 'p_sep_by_space': 127, 'frac_digits': 127, 'thousands_sep': '\xa0', 'n_sign_posn': 127, 'decimal_point': ',', 'int_curr_symbol': '', 'n_cs_precedes': 127, 'p_sign_posn': 127, 'mon_thousands_sep': '', 'negative_sign': '', 'currency_symbol': '', 'n_sep_by_space': 127, 'mon_grouping': [], 'p_cs_precedes': 127, 'positive_sign': '', 'grouping': [3, 0]}
2.5

We see that decimal point is ','; why is then 2,5 printed as 2.5 ??

Thanks

Upvotes: 3

Views: 6355

Answers (1)

PM 2Ring
PM 2Ring

Reputation: 55469

You need to call the locale.str method, not the normal str constructor.

import locale
locale.setlocale(locale.LC_NUMERIC,"ru_RU.utf8")

print locale.localeconv()

fv = 2.5
print locale.str(fv)

output

{'mon_decimal_point': '', 'int_frac_digits': 127, 'p_sep_by_space': 127, 'frac_digits': 127, 'thousands_sep': '\xc2\xa0', 'n_sign_posn': 127, 'decimal_point': ',', 'int_curr_symbol': '', 'n_cs_precedes': 127, 'p_sign_posn': 127, 'mon_thousands_sep': '', 'negative_sign': '', 'currency_symbol': '', 'n_sep_by_space': 127, 'mon_grouping': [], 'p_cs_precedes': 127, 'positive_sign': '', 'grouping': [3, 3, 0]}
2,5

Below is some code that demonstrates a simple locale-aware print function. As I mentioned in my comment, it's generally better to provide an explicit format specification when printing. Sure, the basic print a, b, c form is handy when you don't need fancy output, eg in very simple scripts and during development / debugging, but such output tends to look sloppy when you use it for any but the simplest cases.

Simple format_string % tuple_of_values style formatting is not locale-aware. The locale module does supply a couple of functions (format & format_string) that use the old % formatting protocol. However, % style formatting is being phased out in modern Python in favour of the new style of formatting supported by the built-in format function and str.format. Those format functions provide a local-aware format type specifier for numbers: n; the code below illustrates its use.

# -*- coding: utf-8 -*-

import locale
locale.setlocale(locale.LC_NUMERIC, "ru_RU.utf8")

def lprint(*args):
    lstr = locale.str
    print ' '.join([lstr(u) if isinstance(u, float) else str(u) for u in args])

lprint(1.25, 987654, 42.0, 2.33, u"Росси́я".encode('UTF-8'), 3.456)
print locale.format_string('%.2f %d %.3f %.3f %s %f', (1.25, 987654, 42.0, 2.33, u"Росси́я", 3.456))
print '{0:n} {1:n} {2:n} {3:n} {4:n} {5}'.format(1.25, 987654, 42.0, 2.33, 3.456, u"Росси́я".encode('UTF-8'))

output (in a terminal set to use UTF-8 encoding)

1,25 987654 42 2,33 Россия 3,456
1,25 987654 42,000 2,330 Россия 3,456000
1,25 987 654 42 2,33 3,456 Россия

Note that in the 2nd line we can pass a Unicode string object since locale.format_string is aware of the encoding. In the last line of output 987654 is printed with a thousands separator, which in the Russian locale is a space.

If you use Python 2.7 (or higher) that '{0:n} {1:n} {2:n} {3:n} {4:n} {5}' format string can be simplified to '{:n} {:n} {:n} {:n} {:n} {}'. Of course, in Python 3 the print statement is no longer available: it's been replaced by the print function; you can access that function in later versions of Python 2 by doing from __future__ import print_function before any other import statements.

Upvotes: 1

Related Questions