Временно переопределить локаль с помощью менеджера контекста - PullRequest
0 голосов
/ 07 июня 2018

Есть ли способ временно активировать локаль в пределах блока кода?По сути, я хочу сделать что-то вроде этого:

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 голосов
/ 07 июня 2018

Я обнаружил, что Babel лучше подходит для моего варианта использования:

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

Этот подход полезен всякий раз, когда мне нужно проанализировать десятичную нидерландскую и не требует переопределения каких-либо локалей ввсе.

0 голосов
/ 07 июня 2018

Не уверен, действительно ли ты хочешь это сделать.Локаль может быть глобальной (*) для программы, поэтому она может давать странное поведение в многопоточном контексте.Хуже того, в документации стандартной библиотеки сказано:

Стандарт 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')
0 голосов
/ 07 июня 2018

Вы можете написать простой и понятный контекстный менеджер для этого:

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)
...