使用上下文管理器暂时覆盖语言环境

时间:2018-06-07 09:30:41

标签: python locale

有没有办法暂时激活代码块范围内的区域设置?基本上,我想做这样的事情:

locale.setlocale(locale.LC_NUMERIC, 'nl_BE.utf8')

像这样:

with override_locale(locale.LC_NUMERIC, 'nl_BE.utf8'):
   # Stuff here

这样我也可以避免使用setlocale时可能出现的任何线程安全问题。我的用例是解析上传的文件,其中小数使用逗号而不是句点作为小数分隔符(例如1,25而不是1.25)。

3 个答案:

答案 0 :(得分:1)

我发现Babel更适合我的用例:

>>> parse_decimal('1,25', locale='nl_BE.utf8')
Decimal('1.25')

每当我需要解析荷兰小数并且根本不需要覆盖任何语言环境时,这种方法很有用。

答案 1 :(得分:1)

不确定您是否真的想这样做。语言环境可能是程序的全局(*),因此它可能在多线程上下文中提供奇怪的行为。更糟糕的是,标准库文档说:

  

C标准将语言环境定义为程序范围的属性,可能需要相对昂贵的更改。最重要的是,一些实现被打破,频繁的区域设置更改可能导致核心转储。

话虽如此,可以构建自定义上下文管理器:

class LocaleManager:
    def __init__(self, localename):
        self.name = localename
    def __enter__(self):
        self.orig = locale.setlocale(locale.LC_CTYPE)
        locale.setlocale(locale.LC_ALL, self.name)
    def __exit__(self, exc_type, exc_value, traceback):
        locale.setlocale(locale.LC_ALL, self.orig)

法语Windows上的示例:

>>> print(locale.getlocale())
('fr_FR', 'cp1252')
>>> with LocaleManager("C"):
    print(locale.getlocale())


(None, None)
>>> print(locale.getlocale())
('fr_FR', 'cp1252')

答案 2 :(得分:0)

您可以为此编写一个简单直接的上下文管理器:

from locale import getlocale, setlocale
from contextlib import contextmanager


@contextmanager
def override_locale(category, locale_string):
    prev_locale_string = getlocale(category)
    setlocale(category, locale_string)
    yield
    setlocale(category, prev_locale_string)