Skip to content Skip to sidebar Skip to footer

Temporarily Override Locale With A Context Manager

Is there a way to temporarily activate a locale within the scope of a block of code? Basically, I want to do something like this: locale.setlocale(locale.LC_NUMERIC, 'nl_BE.utf8')

Solution 1:

You can write an easy and straight-forward contextmanager for this:

from locale import getlocale, setlocale
from contextlib import contextmanager


@contextmanagerdefoverride_locale(category, locale_string):
    prev_locale_string = getlocale(category)
    setlocale(category, locale_string)
    yield
    setlocale(category, prev_locale_string)

Solution 2:

I found out that Babel better fits my use case:

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

This approach is useful whenever I need to parse a Dutch decimal and doesn't require overriding any locales at all.

Solution 3:

Unsure whether you really want to do that. The locale may be global(*) to the program, so it could give a weird behaviour in a multithreaded context. Worse, the standard library documentation says:

The C standard defines the locale as a program-wide property that may be relatively expensive to change. On top of that, some implementation are broken in such a way that frequent locale changes may cause core dumps.

That being said, it is possible to build a custom context manager:

classLocaleManager: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)

Example on a French Windows:

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


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

Post a Comment for "Temporarily Override Locale With A Context Manager"