Я думал, что знаю все о кодировках и Python, но сегодня я столкнулся со странной проблемой: хотя консоль настроена на кодовую страницу 850 - и Python сообщает об этом правильно - параметры, которые я помещаю в командную строку, похоже, закодированы вкодовая страница 1252. Если я пытаюсь декодировать их с помощью sys.stdin.encoding, я получаю неправильный результат.Если я предполагаю «cp1252», игнорируя то, что сообщает sys.stdout.encoding, это работает.
Я что-то упустил, или это ошибка в Python?Винда?Примечание: я использую 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-й символ будет иметь порядковое значение 130 вместо 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: Чтение символов Unicode из аргументов командной строки в Python 2.x в Windows .Тем не менее, если командная строка не закодирована, как sys.stdin, и поскольку sys.getdefaultencoding () сообщает об «ascii», кажется, что нет способа узнать ее фактическую кодировку.Я нахожу ответ с помощью расширений win32 довольно странным.