locale.getlocale() проблемы на OSX

Мне нужно, чтобы языковой стандарт системы выполнял ряд действий, в конечном итоге я хочу перевести свое приложение с помощью gettext. Я собираюсь распространять его как на Linux, так и на OSX, но столкнулся с проблемами на OSX Snow Leopard:

$ python
Python 2.5.2 (r252:60911, Jan  4 2009, 17:40:26) 
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.setlocale(locale.LC_ALL, '')
'sv_SE.UTF-8'
>>> locale.getlocale()
('sv_SE', 'UTF8')

$ python
Python 2.6.1 (r261:67515, Jul  7 2009, 23:51:51) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.setlocale(locale.LC_ALL, '')
'C'
>>> locale.getlocale()
(None, None)

Обе системы используют шведский язык. В Linux переменная среды LANG уже имеет значение «sv_SE.UTF-8». Если я передам эту переменную в python на OSX (вместо этого LANG="sv_SE.UTF-8" python), языковой стандарт будет хорошо обнаружен. Но разве locale.getlocale() не должна быть возможность получить любой язык, который есть в операционной системе? Я не хочу заставлять пользователей устанавливать LANG, LC_ALL или вообще любую переменную среды.

Вывод команды locale:

$ locale
LANG=
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=

person pojo    schedule 27.10.2009    source источник
comment
каков ваш вывод locale (в оболочке) в том же окне терминала?   -  person u0b34a0f6ae    schedule 27.10.2009
comment
Добавлен вывод локали в исходное сообщение.   -  person pojo    schedule 28.10.2009


Ответы (6)


Странно на OSX (Smow Leopard 10.6.1) я получаю

$ python
Python 2.6.1 (r261:67515, Jul  7 2009, 23:51:51) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.  
>>> import locale
>>> locale.getlocale()
(None, None)
>>> locale.setlocale(locale.LC_ALL, '')
'en_GB.UTF-8'
>>> locale.getlocale()
('en_GB', 'UTF8')

Редактировать:

Я только что нашел это в списке рассылки Apple python

В основном это зависит от того, что установлено в вашей среде во время выполнения (один из LANG, LANGUAGE, LC_ALL). У меня был LANG=en_GB.UTF-8 в моей среде оболочки.

person mmmmmm    schedule 27.10.2009
comment
Странный. В исходном сообщении я использовал iTerm, но если я использую Terminal.app, я получаю сообщение об ошибке (ValueError: unknown locale: UTF-8). Локаль выглядит странно: «C/UTF-8/C/C/C/C». Может быть, моя система как-то испорчена, но это довольно свежая установка Snow Leopard. - person pojo; 27.10.2009
comment
См. мое редактирование, почему появляется изменение - ваша система не испорчена (ну, не более того, что все OSX python) - извините, должен был добавить это, когда я редактировал - person mmmmmm; 28.10.2009
comment
Я увидел вашу ссылку сейчас, и, насколько я могу судить, это невозможно сделать, поскольку OSX не использует LANG или LC_ALL. Меня заинтриговала переменная __CF_USER_TEXT_ENCODING, но ее анализ кажется глупым. IMO getlocale() должен вызывать соответствующие API и анализировать их для вас, а не полагаться на некоторые переменные среды. - person pojo; 28.10.2009
comment
@pojo, и вы были довольно правы: это ошибка Python, и похоже, что они могут в конечном итоге использовать собственные API-интерфейсы локали вместо переменных среды. Увы, до сих пор не исправлено. bugs.python.org/issue18378 - person hmijail mourns resignees; 01.03.2016

Похоже, вы можете изменить локаль, изменив переменную среды LC_ALL.

$ export LC_ALL=C
$ python
Python 2.5.1 (r251:54863, Feb  6 2009, 19:02:12) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.getlocale()
(None, None)
>>> locale.setlocale(locale.LC_ALL, "")
'C'
>>> locale.getlocale()
(None, None)    

$ export LC_ALL=en_GB.UTF-8
$ python
Python 2.5.1 (r251:54863, Feb  6 2009, 19:02:12) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.getlocale()
(None, None)
>>> locale.setlocale(locale.LC_ALL, "")
'en_GB.UTF-8'
>>> locale.getlocale()
('en_GB', 'UTF8')
person Anand Chitipothu    schedule 27.10.2009
comment
Но я не вижу смысла явно устанавливать LC_ALL таким образом, чтобы мое приложение правильно определяло язык. - person pojo; 28.10.2009

По общему признанию, ужасный хак, но я вставил это:

import platform

# ...

# XXX horrendous OS X invalid locale hack
if platform.system() == 'Darwin':
    import locale
    if locale.getlocale()[0] is None:
        locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')

в самом начале моей программы. После этого я мог запускать свою программу, используя немодифицированную среду оболочки на всех ОС, относящихся ко мне (моя программа все равно определяет язык, который будет использоваться позже при ее обработке).

person Jacob Oscarson    schedule 11.01.2012
comment
+1. Это это ужасный хак, но он необходим, учитывая, что это ошибка Python. (Подробнее в моем ответе; P) - person hmijail mourns resignees; 12.02.2017

Из здесь: попробуйте добавить или отредактировать файл ~/.profile или ~/.bash_profile, чтобы он правильно экспортировал настройки вашей локали при запуске нового сеанса.

export LC_ALL=en_US.UTF-8  
export LANG=en_US.UTF-8
person Renaud    schedule 31.07.2013
comment
1) Переменные локали могут быть установлены самой программой эмуляции терминала, так что это только скрывает проблему. 2) Переменные локали уже установлены правильно, но python их не понимает. - person hmijail mourns resignees; 01.03.2016

Старый вопрос, но это может помочь другим: это ошибка Python, которая по состоянию на март 2016 года все еще не устранена ни в Python 2, ни в 3: https://bugs.python.org/issue18378 .

Подводя итог, можно сказать, что Python предполагает GNU-подобные локали и не допускает (верных POSIX) расхождений, подобных тем, которые существуют в средах BSD (как и OS X). И локаль UTF8 существует в BSD, а не в Linux, отсюда и проблема.

Что касается решений или отладки: локальные переменные среды могут быть установлены с помощью Terminal.app (см. «Настройки» — «Профили» — «Дополнительно» — «Международный»; аналогично для iTerm или чего-то еще). Таким образом, можно найти переменные среды локали, установленные в окне терминала, но найти переменные, НЕ установленные при запуске упакованного приложения.

В некоторых случаях (например, Sphinx в python 2.7 и 3.5, умирающий в OS X из-за «ValueError: unknown locale: UTF-8»), решением является отключение флажка предпочтения для установки переменных среды локали.

Но это может вызвать проблемы в других программах: если переменные локали не установлены, bash 4.3 (от MacPorts) будет жаловаться при каждом запросе «предупреждение: setlocale: LC_CTYPE: невозможно изменить локаль (): Нет такого файла или каталога». .

Итак, учитывая, что ошибка находится в Python, обходной путь, вероятно, должен быть выполнен в программе python (как в ответе @Jacob Oscarson) или вызове python (путем установки переменных локали на некоторое адекватное значение).

person hmijail mourns resignees    schedule 01.03.2016

моя установка

$ system_profiler SPSoftwareDataType
Software:

    System Software Overview:

      System Version: macOS 11.4 (20F71)
      Kernel Version: Darwin 20.5.0

Если текущий язык в System Preferences > Language & ReginonEnglish, то

Python 3.9.5 (v3.9.5:0a7dcbdb13, May  3 2021, 13:17:02) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.getdefaultlocale()
(None, 'UTF-8')
>>> 

и вывод команды низкоуровневой оболочки

$ locale
LANG=""
LC_COLLATE="C"
LC_CTYPE="UTF-8"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=

Если текущий язык Chinese, Simplified, то

$ py3
Python 3.9.5 (v3.9.5:0a7dcbdb13, May  3 2021, 13:17:02) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.getdefaultlocale()
('zh_CN', 'UTF-8')
>>> 

и вывод команды низкоуровневой оболочки

$ locale
LANG="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_CTYPE="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_ALL=

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

person kakyo    schedule 04.07.2021