获取Windows上的当前区域设置

时间:2017-12-20 16:40:31

标签: python windows python-3.x locale

上下文

在Windows上使用python获取区域设置似乎已被破坏:

(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
>>>

我对Windows了解不多,但我检查fr-FR属于the correct locale names for Windows。请注意,使用en-USen-GB会得到相同的结果。

然而设置区域设置正常工作,因为:

  • 使用任何未知值的locale.setlocale()会引发异常:
    >>> 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
    >>>
  • 一旦设置,就可以检查它是否被考虑在内:
    >>> 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'
    >>>

问题

我需要暂时将语言环境设置为en-US(为了执行需要此语言环境的一些操作),然后切换回默认语言环境。如果locale.getlocale()被破坏,怎么可能呢?我已经阅读了python doc about locale,但无法找出实现这一目标的任何解决方法(也不知道是否可行)。

1 个答案:

答案 0 :(得分:1)

以下是我试图在你的问题评论中描述的locale模块的补丁。

首先是猴子修补模块,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.

样本用法:

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.