简体   繁体   中英

Getting the current locale on windows

Context

Getting the locale with python on Windows seems to be broken:

(trash0) PS C:\Users\myname\venv\trash0\Lib\site-packages> python.exe
Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.platform
'win32'
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'fr-FR')
'fr-FR'
>>> locale.getlocale()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python36-32\lib\locale.py", line 581, in getlocale
    return _parse_localename(localename)
  File "C:\Program Files\Python36-32\lib\locale.py", line 490, in _parse_localename
    raise ValueError('unknown locale: %s' % localename)
ValueError: unknown locale: fr-FR
>>>

I do not know much about Windows but I have checked fr-FR belongs to the correct locale names for Windows . Note that using en-US or en-GB get the same result.

Yet setting the locale works correctly because:

  • using locale.setlocale() with any unknown value would raise an exception:
  >>> locale.setlocale(locale.LC_ALL, 'anythingundefined')
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "C:\Program Files\Python36-32\lib\locale.py", line 598, in setlocale
      return _setlocale(category, locale)
  locale.Error: unsupported locale setting
  >>>
  • once set, it's possible to check it is taken into account:
  >>> locale.setlocale(locale.LC_ALL, 'fr-FR')
  'fr-FR'
  >>> locale.str(12.3)
  '12,3'
  >>> locale.setlocale(locale.LC_ALL, 'en-GB')
  'en-GB'
  >>> locale.str(12.3)
  '12.3'
  >>>

Question

I need to temporarily set the locale to en-US (in order to perform some things that require this locale) and then switch back to the default locale. How is it possible to do it if locale.getlocale() is broken? I've read the python doc about locale but can't figure out any workaround to achieve this (nor whether it is possible at all).

Here's how to monkey patch the locale module as I was trying to describe in my comments under your question.

First the monkey-patching module, locale_patch.py :

""" Module that monkey-patches the locale module so it remembers the last
arguments to setlocale() that didn't raise an exception and will allow them to
be retrieved later by calling a new function named setting_values() which also
gets added.
"""
import locale as _locale

_last_category, _last_locale = None, None

def my_setlocale(category, locale=None):
    global _last_category, _last_locale

    try:
        result = _orig_setlocale(category, locale)
    except _locale.Error:
        raise  # Didn't work, ignore arguments.

    if locale is not None:  # Was a setting modified by call?
        _last_category, _last_locale = category, locale  # Remember args.

    return result

def setting_values():
    global _last_category, _last_locale

    if _last_category is None:
        raise _locale.Error('setlocale() has never been called to change settings')

    return _last_category, _last_locale


# Monkey-patch the module.
_orig_setlocale = _locale.setlocale
_locale.setlocale = my_setlocale
_locale.setting_values = setting_values  # New module function.

Sample usage:

import locale
import locale_patch  # Apply monkey-patch(es).

try:
    locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8') # locale.Error: unsupported locale setting
except locale.Error:
    print("locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8') didn't work")
try:
    print(locale.setting_values())
except locale.Error:
    print("locale.setting_values() didn't work")  # Expected.

try:
    locale.setlocale(locale.LC_ALL, locale='fr_FR.UTF-8')
except locale.Error:
    print("locale.setlocale(locale.LC_ALL, locale='fr_FR.UTF-8') didn't work")
try:
    print(locale.setting_values())
except locale.Error:
    print("locale.setting_values() didn't work")  # Expected.

locale.setlocale(locale.LC_ALL, 'fr-FR')
results = locale.setting_values()
print(results)  # -> (0, 'fr-FR')  # The 0 is the numeric value of locale.LC_ALL

locale.setlocale(*results)  # Works OK.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM