Ошибка UnicodeDecodeError при ssh из OS X

#python #django #macos #ssh #locale

#python #django #macos #ssh #язык

Вопрос:

Мое приложение Django загружает некоторые файлы при запуске (или когда я выполняю команду управления). Когда я использую ssh с одной из моих машин Arch или Ubuntu, все работает нормально, я могу успешно запускать любые команды и миграции.

Но когда я использую ssh из OS X (у меня El Capital) и пытаюсь сделать то же самое, я получаю эту ошибку:

 UnicodeDecodeError: 'ASCII' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
 

Чтобы открыть мои файлы, я использую with open(path_to_file) as f: ...

Ошибка возникает при sshing как из iterm, так и из терминала. Я узнал, что причиной была LC_CTYPE переменная среды. Он не был установлен на других моих компьютерах с Linux, но на Mac это было UTF-8 так, что после того, как я подключился к серверу по ssh, он был установлен таким же. Ошибка была исправлена после того, как я сбросил LC_CTYPE настройки.

Итак, актуальный вопрос в том, что произошло и как избежать этого дальше? Я могу отключить эту переменную на своем локальном компьютере, но приведет ли это к каким-либо негативным последствиям? И каков наилучший способ сделать это?

Ответ №1:

Ваш терминал на вашем локальном компьютере использует кодировку символов. Используемая им кодировка выглядит как UTF-8. Когда вы входите на свой сервер (кстати, на какой ОС он запускается?) программы, которые там запускаются, должны знать, какую кодировку поддерживает ваш терминал, чтобы они отображали материал по мере необходимости. Они получают эту информацию из LC_CTYPE . ssh правильно устанавливает его в UTF-8, потому что это то, что поддерживает ваш терминал.

Когда вы отменяете LC_CTYPE настройку, ваши программы используют значение по умолчанию, ASCII . Программы теперь отображаются в ASCII вместо UTF-8 , который работает, потому UTF-8 что обратно совместим с. ASCII Однако, если программе необходимо отобразить специальный символ, которого не существует ASCII , он не будет работать.

Хотя из предоставленной вами информации мне не совсем понятно, почему система ведет себя таким образом, я могу сказать вам, что сброс LC_CTYPE настроек — это плохой обходной путь. Чтобы избежать проблем в будущем, было бы лучше убедиться, что все ваши терминалы на всех ваших машинах используют UTF-8, и избавиться от ASCII.

Когда вы пытаетесь получить доступ к open файлу, Python использует набор символов терминала (т.е. LC_CTYPE ‘s). Я никогда не совсем понимал, почему это сделано таким образом; почему набор символов вашего терминала должен указывать кодировку, которую имеет файл? Тем не менее, это так, и способ исправить проблему правильно — использовать encoding параметр open , если вы используете Python 3, или codecs стандартный библиотечный модуль, если вы используете Python 2.

Комментарии:

1. На самом деле я просто погуглил, что UTF-8 это недопустимый LC_CTYPE, поэтому я добавил вместо export LC_ALL=en_US.UTF-8 и export LANG=en_US.UTF-8 к моему .bash_profile , и это устранило проблему. Кстати, я использую Ubuntu 16.04 в качестве серверной машины. И я не знал, что open использует LC_CTYPE для определения кодировки файлов, это действительно странно. Спасибо за это. Я приму ваш ответ.

Ответ №2:

У меня была аналогичная проблема после обновления моей OS-X, при подключении по ssh к серверу UNIX символ авторского права не был закодирован, потому что язык UTF-8 не был настроен должным образом. Я решил проблему, сняв флажок «Устанавливать переменные среды locale при запуске» в настройках моего терминала (ов).