Setting Python locale doesn't work

2019-01-25 15:03发布

问题:

So I've been trying to set the Python locale. I want to because I want to use the weekday name in local language (using strftime('%A')). But currently the weekday is printed in English even though I tried setting the locale several ways. I am running this on a RPi2 with Ubuntu Mate.

I have tried the solutions in this topic What is the correct way to set Python's locale on Windows?

I tried explicitly setting locale to nl_NL.utf8:

$> locale -a
$> python3
>>> import locale
>>> locale.setlocale(locale.LC_ALL,'nl_NL.utf-8')

I also tried setting an empty string, a suggested in the last answer:

>>> locale.setlocale(locale.LC_ALL, '')

In both cases when I try

>>> locale.getlocale()

I see nl_NL.utf8

But I still get the weekday in English! Haven't been able to find much about this on the internetz except for the above topic and I couldn't get this fixed.


Edit:

I have tried all 3 options. The first one returns a weird result:

~/Documenten$ python3
Python 3.4.3+ (default, Oct 14 2015, 16:03:50) 
[GCC 5.2.1 20151010] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.getlocale(locale.LC_TIME)
(None, None)
>>> locale.setlocale(locale.LC_TIME, 'nl_NL.utf-8')
'nl_NL.utf-8'
>>> locale.getlocale(locale.LC_TIME)
('nl_NL', 'UTF-8')
>>> exit()
jeffrey@jeffrey-desktop:~/Documenten$ python3
Python 3.4.3+ (default, Oct 14 2015, 16:03:50) 
[GCC 5.2.1 20151010] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.getlocale(locale.LC_TIME)
(None, None)

It seems like nothing is saved. Am I wrong in assuming you set your locale once and then the system will remember this? The second option:

~/Documenten$ python3
Python 3.4.3+ (default, Oct 14 2015, 16:03:50) 
[GCC 5.2.1 20151010] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import calendar
>>> calendar.day_name[2]
'Wednesday'
>>> import locale
>>> locale.nl_langinfo(locale.DAY_2)
'Monday'

Even though I am trying to get a Dutch weekday name I still get an English name in return. Besides that this method starts counting from sunday and not monday. Am I doing anything wrong? The third suggestion got me my weekday name, thanks! But I'm still wondering why the first doesn't work? I am using this script on my own device and would like to work with a correct global locale.


Edit2:

yes, calling locale.setlocale() in Python does not affect future python processes. Configure environment variables instead, see How to set all locale settings in Ubuntu.

Ok! So that is why it didn't work. I assumed I had set the locale for any future use in Python, like an environment variable but then only for Python.

I have a bash script creating files and this Python script should delete it after some time (learning to code, didn't know Python when I wrote the Bash script). Bash's "date" method seems to pick up the locale some way or the other. I'll go ahead and see what I can fix for Python. This is what I see when I type $ locale:

LANG=nl_NL.UTF-8
LANGUAGE=nl:en
LC_CTYPE="nl_NL.UTF-8"
LC_NUMERIC="nl_NL.UTF-8"
LC_TIME="nl_NL.UTF-8"
LC_COLLATE="nl_NL.UTF-8"
LC_MONETARY="nl_NL.UTF-8"
LC_MESSAGES="nl_NL.UTF-8"
LC_PAPER="nl_NL.UTF-8"
LC_NAME="nl_NL.UTF-8"
LC_ADDRESS="nl_NL.UTF-8"
LC_TELEPHONE="nl_NL.UTF-8"
LC_MEASUREMENT="nl_NL.UTF-8"
LC_IDENTIFICATION="nl_NL.UTF-8"
LC_ALL=

回答1:

It seems like nothing is saved. Am I wrong in assuming you set your locale once and then the system will remember this

yes, calling locale.setlocale() in Python does not affect future python processes. Configure environment variables instead, see How to set all locale settings in Ubuntu.

Bash's "date" method seems to pick up the locale some way or the other.

date calls setlocale(LC_ALL, "") at the start i.e., you need to call setlocale() at least once per process to enable $LANG locale instead of C locale.


setlocale(LC_ALL, '') sets locale according to $LANG variable first, not $LANGUAGE (it is related but different: "The GNU gettext search path contains 'LC_ALL', 'LC_CTYPE', 'LANG' and 'LANGUAGE', in that order.").

It is enough to set LC_TIME category (on Ubuntu):

>>> import locale
>>> import time
>>> time.strftime('%A')
'Tuesday'
>>> locale.getlocale(locale.LC_TIME)
('en_US', 'UTF-8')
>>> locale.setlocale(locale.LC_TIME, 'ru_RU.UTF-8')
'ru_RU.UTF-8'
>>> time.strftime('%A')
'Вторник'
>>> locale.getlocale(locale.LC_TIME)
('ru_RU', 'UTF-8')

If setlocale() hasn't raised locale.Error: unsupported locale setting then the corresponding locale category is set successfully.

You could also get the weekday name knowing its position (in the same python session where the locale is changed):

>>> import calendar
>>> calendar.day_name[1]
'Вторник'
>>> locale.nl_langinfo(locale.DAY_3)
'Вторник'

A portable way, to print a weekday in a given locale without modifying a global state, is to use babel module:

>>> from datetime import date
>>> from babel.dates import format_date # $ pip install babel
>>> format_date(date.today(), format='EEEE', locale='en')
'Tuesday'
>>> format_date(date.today(), format='EEEE', locale='ru')
'вторник'
>>> format_date(date.today(), format='EEEE', locale='nl')
'dinsdag'