Ответ 1
Примечание. Что было сделано для решения этой проблемы, это передать encoding='UTF-8'
в вызов open
. Если вы столкнулись с этой проблемой и ищете исправление, это работает. Остальная часть сообщения - это акцент на том, почему.
Что произойдет
Как сказал Лукас, в документах указывается:
В некоторых системах необходимо вызвать setlocale() для получения пользовательских настроек
Изначально string.letters имеет значение lowercase + uppercase
:
lowercase = 'abcdefghijklmnopqrstuvwxyz'
uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
letters = lowercase + uppercase
Однако, когда вы вызываете getpreferredencoding()
, модуль _locale
переопределяет его, вызывая PyDict_SetItemString(string, "letters", ulo);
после его создания внутри fixup_ulcase(void)
со следующим:
/* create letters string */
n = 0;
for (c = 0; c < 256; c++) {
if (isalpha(c))
ul[n++] = c;
}
ulo = PyString_FromStringAndSize((const char *)ul, n);
if (!ulo)
return;
if (string)
PyDict_SetItemString(string, "letters", ulo);
Py_DECREF(ulo);
В свою очередь, это называется в PyLocale_setlocale
, который действительно setlocale
, который вызывается getpreferredencoding
- здесь кодом http://hg.python.org/cpython/file/07a6fca7ff42/Lib/locale.py#l612:
def getpreferredencoding(do_setlocale = True):
"""Return the charset that the user is likely using,
according to the system configuration."""
if do_setlocale:
oldloc = setlocale(LC_CTYPE)
try:
setlocale(LC_CTYPE, "")
except Error:
pass
result = nl_langinfo(CODESET)
setlocale(LC_CTYPE, oldloc)
return result
else:
return nl_langinfo(CODESET)
Как этого избежать?
Попробуйте getpreferredencoding(False)
Почему это не происходит в Windows?
В Windows используется другой код для получения локали, как вы можете видеть здесь.
В Python 3
В Python 3 getdefaultlocale
не принимает логическую переменную setlocale и не вызывает сам setlocale, поскольку вы можете видеть здесь.