Мне показалось, что я знаю все о кодировках и Python, но сегодня я столкнулся с какой-то странной проблемой: хотя консоль настроена на кодовую страницу 850 - и Python сообщает об этом правильно - параметры, введенные в командной строке, кажутся закодированными на кодовой странице 1252. Если я попытаюсь их декодировать с помощью sys.stdin.encoding, я получаю неправильный результат. Если я предполагаю 'cp1252', игнорируя то, что сообщает sys.stdout.encoding, он работает.Python, windows console и encodings (cp 850 vs cp1252)
Я что-то упустил или это ошибка в Python? Windows? Примечание. Я запускаю Python 2.6.6 в Windows 7 EN, языковой стандарт установлен на французский (Швейцария).
В тестовой программе, приведенной ниже, я проверяю, что литералы правильно интерпретируются и могут быть напечатаны - это работает. Но все значения Перехожу в командной строке, кажется, закодированы неправильно:
#!/usr/bin/python
# -*- encoding: utf-8 -*-
import sys
literal_mb = 'utf-8 literal: üèéÃÂç€ÈÚ'
literal_u = u'unicode literal: üèéÃÂç€ÈÚ'
print "Testing literals"
print literal_mb.decode('utf-8').encode(sys.stdout.encoding,'replace')
print literal_u.encode(sys.stdout.encoding,'replace')
print "Testing arguments (stdin/out encodings:",sys.stdin.encoding,"/",sys.stdout.encoding,")"
for i in range(1,len(sys.argv)):
arg = sys.argv[i]
print "arg",i,":",arg
for ch in arg:
print " ",ch,"->",ord(ch),
if ord(ch)>=128 and sys.stdin.encoding == 'cp850':
print "<-",ch.decode('cp1252').encode(sys.stdout.encoding,'replace'),"[assuming input was actually cp1252 ]"
else:
print ""
В недавно созданной консоли, при запуске
C:\dev>test-encoding.py abcé€
я получаю следующие выходные данные
Testing literals
utf-8 literal: üèéÃÂç?ÈÚ
unicode literal: üèéÃÂç?ÈÚ
Testing arguments (stdin/out encodings: cp850/cp850)
arg 1 : abcÚÇ
a -> 97
b -> 98
c -> 99
Ú -> 233 <- é [assuming input was actually cp1252 ]
Ç -> 128 <- ? [assuming input was actually cp1252 ]
в то время как Я ожидал бы, что у 4-го символа будет порядковое значение вместо 233 (см. Кодовые страницы 850 и 1252).
Примечания: значение 128 для символа евро является загадкой - поскольку cp850 не имеет его. В противном случае '?' - cp850 не может печатать символы, и я использовал «replace» в конверсиях.
Если изменить кодовую страницу консоли в 1252, выпуская chcp 1252
и запустить ту же команду, я (правильно) получить
Testing literals
utf-8 literal: üèéÃÂç€ÈÚ
unicode literal: üèéÃÂç€ÈÚ
Testing arguments (stdin/out encodings: cp1252/cp1252)
arg 1 : abcé€
a -> 97
b -> 98
c -> 99
é -> 233
€ -> 128
Любые идеи, что я не хватает?
Редактировать 1: Я только что проверил, прочитав sys.stdin. Это работает так, как ожидалось: в cp850 ввод «é» приводит к порядковому значению 130. Таким образом, проблема действительно для командной строки. Итак, является ли командная строка обработанной иначе, чем стандартный ввод?
Редактировать 2: Кажется, у меня были неправильные ключевые слова. Я нашел еще одну очень близкую тему о SO: Read Unicode characters from command-line arguments in Python 2.x on Windows. Тем не менее, если командная строка не закодирована как sys.stdin, а так как sys.getdefaultencoding() сообщает «ascii», кажется, что нет способа узнать ее фактическую кодировку. Я нахожу ответ, используя расширения win32 довольно хаки.
Для Linux обычно 'locale.getpreferredencoding()' или, после использования 'locale.setlocale()' - 'locale.getlocale() [1]' дает правильную кодировку для доступа к консоли и среде. Хотя, жестко запрограммированный UTF-8 часто достаточно хорош для большинства современных систем (поэтому это лучшее значение возврата). –