Языковой стандарт Python по умолчанию (неподдерживаемый языковой стандарт)

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

$ docker run --rm -it python:3.6 bash
root@bcee8785c2e1:/# locale
LANG=C.UTF-8
LANGUAGE=
LC_CTYPE="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_PAPER="C.UTF-8"
LC_NAME="C.UTF-8"
LC_ADDRESS="C.UTF-8"
LC_TELEPHONE="C.UTF-8"
LC_MEASUREMENT="C.UTF-8"
LC_IDENTIFICATION="C.UTF-8"
LC_ALL=
root@bcee8785c2e1:/# locale -a
C
C.UTF-8
POSIX
root@bcee8785c2e1:/# python
Python 3.6.9 (default, Jul 13 2019, 14:51:44) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> curr = locale.getlocale()
>>> curr
('en_US', 'UTF-8')
>>> locale.setlocale(locale.LC_ALL, curr)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/locale.py", line 598, in setlocale
    return _setlocale(category, locale)
locale.Error: unsupported locale setting
>>>

Я не уверен, почему getlocale возвращает en_US? Его нет нигде в моей среде vars (и я не уверен, где еще он может быть в моей оболочке?).

В любом случае, я не могу setlocale со значением из getlocale, что мне кажется странным.

У кого-нибудь есть руководство здесь?

Очень признателен!


person Hoopes    schedule 11.12.2019    source источник
comment
Я не думаю, что C.UTF-8 является допустимой локалью. C (синоним POSIX) предназначен и предназначен для строго резервного копирования byte = char [На телефоне, поэтому не могу проверить]   -  person Rusi    schedule 07.01.2020
comment
Это немного сложнее???? Продолжение комментария выше в ответе ниже   -  person Rusi    schedule 10.01.2020


Ответы (2)


Для первой части: Имеет ли это значение? Насколько я знаю, я никогда не вижу различий, пока вы не вызовете setlocale(), поэтому мы находимся во второй части:

Вы должны использовать:

import locale
curr = locale.getdefaultlocale()
locale.setlocale(locale.LC_ALL, curr)

так что getdefaultlocale() и не только getlocale(). Я также не совсем понимаю причину иметь оба. Возможно ли, что это ошибка Python, которая не может распознать C.xxx.

person Giacomo Catenazzi    schedule 12.12.2019
comment
Это сумасшествие, тот же результат: ('en_US', 'UTF-8')... и та же ошибка... - person Hoopes; 12.12.2019
comment
Но это не крах. Примечание. Я не уверен, есть ли проверяемые различия (с выводами), только C.utf-8 включает en-US.utf-8. [Здесь Python 3.7.3 с `LC_ALL='C.utf8' python3/tmp/b.py`] - person Giacomo Catenazzi; 12.12.2019
comment
Ну, является ли ошибка python, debian, docker или libc спорным. C.UTF-8, безусловно, является магнитом для ошибок — см. мой ответ ниже, особенно отчеты об ошибках Haskell и Redhat. - person Rusi; 10.01.2020
comment
@Rusi: но твой ответ - не ответ. C.UTF-8 может быть плохо (но я посмотрел стандарт, и он должен быть правильным, еще и потому, что две части разные: одна о том, как программа должна подготовить вещи [зависит от пользователя], вторая о том, как отображать [зависит от терминала]. Но проблема здесь заключается в том, что ОП использовал неправильную функцию: он запросил строку для локали, которую нельзя использовать для установки локали.Строка представляет собой интерпретацию строки локали (полезную для других целей), но это не системная локаль, поэтому ее нельзя используется безопасно. C.UTF-8 — это один случай, но их гораздо больше [локальная семантика сложна] - person Giacomo Catenazzi; 11.01.2020

C.UTF-8 — Недавний непереносимый дебианизм

Намерение C.UTF-8 хорошее, но реализация еще не совсем. На данный момент избегайте, пока он не стабилизируется.

Некоторое обсуждение контекста

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

Обсуждение haskell, показывающее переносимый кроссплатформенный материал — в данном случае haskell-stack, но косвенно также докер — становится сложнее и менее надежным с использованием C.UTF-8.

Намерение

Debian (также) инициировал C. UTF-8 и намерение правильное.

Сегодняшние Linux-системы интенсивно локализованы — множество локалей, детальный выбор вариантов LC_* и т. д. и т. д. Но все это не включено по умолчанию: если система локалей нарушена, система сломана. Причина, по которой сломанная локальная система не так серьезна, как, скажем, сломанное ядро, fstab или grub и т. д., заключается в...

Локаль C

локаль C (синоним POSIX) всегда будет доступен в качестве запасного варианта, если другие вещи сломаются. Так, например, вы увидите не локализованные ошибки, а английский — не моджибаке, пустые прямоугольники или вопросительные знаки!

По большому счету вы получаете такого рода предупреждения а не ошибки, а в остальном все работает.

Но C = POSIX подразумевает устаревший ASCII, а не UTF-8 везде — нежелательный побочный эффект устаревшего.

Чтобы сделать это наследие все менее и менее необходимым, даже в качестве запасного варианта, Debian представил всегда доступную локаль C.UTF-8.

Улов? Он всегда доступен...

Только в Дебиан

Это означает, что последний Debian, производные, такие как Ubuntu, также недавние. Но не (пока) другие системы.

Короче говоря, C.UTF-8 не является универсальным, не переносимым, хрупким и, следовательно, его можно избежать ... по крайней мере, на данный момент, по крайней мере, в клиент-серверных, виртуализированных (контейнерных) и т. д. системах, таких как докер. ....

Практический результат

Вам необходимо явно установить устаревшие локали, такие как en_US.UTF-8. (Люди, которым нужна разумная международная английская локаль и не нужна en_US, могут захотеть проверить en_DK.UTF-8).

Да, это включает в себя некоторое количество

Пачкать руки

Вот коллекция ссылок по настройке локали, ориентированной на докер.

Я не одобряю один анти-шаблон, который повторяется в приведенном выше, но это слишком далеко (от этого вопроса), чтобы расширить это, так что вкратце:

Установка языкового стандарта обычно должна только включать настройку LANG. Установка LC_ALL , особенно вместе с LANG, недопустима.

Из вики Debian

⚠️ ВНИМАНИЕ

Использование LC_ALL настоятельно не рекомендуется, так как оно переопределяет все. Пожалуйста, используйте его только при тестировании и никогда не устанавливайте его в файле запуска.

person Rusi    schedule 10.01.2020
comment
en_DK Это сумасшедшая аберрация, которую, возможно, можно было бы защитить, если бы это было доступно везде по умолчанию; но, увы, это не так. Кроме того, IIRC имеет далеко не идеальные значения для дат и валюты. Возможно, см. также unix. stackexchange.com/questions/62316/ - person tripleee; 11.01.2020
comment
@tripleee Я ослабил ссылку на en_DK. Можете удалить его, если хотите (это вряд ли относится к q или a!) - person Rusi; 11.01.2020