Почему все эти команды Юникода работают ПРАВИЛЬНО в Python? Они все печатают мой персонаж правильно, независимо от того, что я делаю - PullRequest
2 голосов
/ 22 января 2012

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

Я пробовал это в Eclipse с Pydev.Я использую Python 2.6.6 (из-за некоторой библиотеки, которая не поддерживает Python 2.7).

Во-первых, без использования модуля кодеков

# -*- coding: utf-8 -*-

file1 = open("samoloty1.txt", "w")
file2 = open("samoloty2.txt", "w")
file3 = open("samoloty3.txt", "w")
file4 = open("samoloty4.txt", "w")
file5 = open("samoloty5.txt", "w")
file6 = open("samoloty6.txt", "w")

# I know that this is weird, but it shows that whatever i do, it not ruin anything...
print u"ą✈✈"
file1.write(u"ą✈✈")
print "ą✈✈"
file2.write("ą✈✈")

print "ą✈✈".decode("utf-8")
file3.write("ą✈✈".decode("utf-8"))
print "ą✈✈".encode("utf-8")
file4.write("ą✈✈".encode("utf-8"))

print u"ą✈✈".decode("utf-8")
file5.write(u"ą✈✈".decode("utf-8"))
print u"ą✈✈".encode("utf-8")
file6.write(u"ą✈✈".encode("utf-8"))

file1.close()
file2.close()
file3.close()
file4.close()
file5.close()
file6.close()

file1 = open("samoloty1.txt", "r")
file2 = open("samoloty2.txt", "r")
file3 = open("samoloty3.txt", "r")
file4 = open("samoloty4.txt", "r")
file5 = open("samoloty5.txt", "r")
file6 = open("samoloty6.txt", "r")

print file1.read()
print file2.read()
print file3.read()
print file4.read()
print file5.read()
print file6.read()

Каждый из этих отпечатков работает правильно, и я неНе получайте забавных символов.

Также я попробовал это: я удаляю все файлы, сделанные в предыдущем тесте, и меняю только те строки:

file1 = open("samoloty1.txt", "w")

на те:

file1 = codecs.open("samoloty1.txt", "w", encoding='utf-8')

и снова все работает ...

Кто-нибудь может привести примеры, что работает, а что нет?

Должен ли это быть отдельный вопрос? Я загружаю веб-страницы через:

content = urllib.urlopen(some_url).read()
ucontent = unicode(content, encoding) # i get encoding from headers

Это правильно и достаточно?Что мне делать дальше, чтобы сохранить его в файле utf-8?(Я спрашиваю, потому что, что бы я ни делал раньше, это просто работает ...)

** ОБНОВЛЕНИЕ **

Вероятно, все работает нормально, потому что PyDev (или просто Eclipse) имеет терминал, закодированный в UTF-8.Поэтому для тестов я использовал cmd из Windows 7 и получаю некоторые ошибки.Теперь все рушилось, как и ожидалось.: D Здесь я показываю, что я изменил, чтобы заставить его работать снова (и все эти изменения являются разумными для меня, и они согласны с тем, что я узнал в ответах и ​​в документах по документации Python).

print u"ą✈✈".encode("utf-8") # added encode
file1.write(u"ą✈✈".encode("utf-8")) # added encode
print "ą✈✈"
file2.write("ą✈✈")

print "ą✈✈" # removed .decode("utf-8")
file3.write("ą✈✈") # removed .decode("utf-8"))
print "ą✈✈" # removed .encode("utf-8")
file4.write("ą✈✈") # removed .encode("utf-8"))

print u"ą✈✈".encode("utf-8") # changed from .decode("utf-8")
file5.write(u"ą✈✈".encode("utf-8")) # changed from .decode("utf-8")
print u"ą✈✈".encode("utf-8")
file6.write(u"ą✈✈".encode("utf-8"))

И, как кто-то сказал, когда я использую кодеки, мне не нужно каждый раз использовать encode () перед записью в файл.:) Вопрос в том, какой ответ следует пометить как правильный?

Ответы [ 4 ]

3 голосов
/ 22 января 2012

Вам просто повезло, что кодировка вашей консоли по умолчанию utf-8.

Если вы передаете объект unicode методу write метода файлового объекта (sys.stdout)объект неявно декодируется с помощью его атрибута encoding.

Те, кто работает в Windows, не так удачливы: Как обойти Python: проблема «Сообщения WindowsError неправильно закодированы»?

1 голос
/ 22 января 2012

Все эти упражнения по написанию фрагмента кода сводятся к двум ситуациям:

  • при записи строки в файл
  • при попытке записать строку юникода в файл

Позволяет вызывать строку как s и строку юникода как u.

Тогда fileN.write (s) имеет смысл, а fileN.write (u) - нет. Я не знаю о вашей настройке (возможно, вы внесли некоторые изменения в python для сайта), но следующие ошибки здесь ожидаются:

# -*- coding: utf-8 -*-                                                                                                                                                                               
ff = open("ff.txt", "w")
ff.write(u"ą✈✈")
ff.close()

с:

Traceback (most recent call last):
  File "ex.py", line 5, in <module>
    ff.write(u"ą✈✈")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

Это означает, что строка unicode должна быть изменена на строку перед записью в файл. И ваш пример file6 показывает, как это сделать:

u"ą✈✈".encode("utf-8")

Волшебная строка -*- coding: utf-8 -*- - это та, которая позволяет вам писать строковые литералы Юникода WYSIWYG способом: u"ą✈✈", это не поможет вам определить вашу кодировку в любой другой ситуации.

Таким образом, не передавайте метод .write () в Python2.6 какой-либо строке Юникода. Хорошей практикой является работа со строками Unicode в вашем коде, но преобразование из / в конкретное кодирование на границах ввода / вывода.

Пример кодеков хорош, как и urllib.

1 голос
/ 22 января 2012

То, что вы делаете, правильно. См. это Python Unicode HOWTO для получения дополнительной информации.

Общие принципы:

  1. Когда двоичные данные поступают в ваше приложение (например, open(), urllib.urlopen()), используйте метод decode(), чтобы получить строку Unicode.
    • Если строка байтов недопустима для предоставленной кодировки, вы можете получить UnicodeDecodeError. В этом случае выполните одно из следующих действий:
      1. Используйте второй аргумент для decode для замены или игнорирования плохих символов
      2. старайся выяснить, что такое настоящая кодировка
      3. исправить ввод, если он действительно искажен.
    • Для файлов вы можете использовать оболочки codecs.open, чтобы сделать это прозрачно для вас.
    • Сетевые данные обычно нужно декодировать вручную, но иногда полезная нагрузка объявляет свою собственную кодировку (например, html, XML), а иногда она не соответствует заголовку!
    • Для данных базы данных, как правило, драйвер базы данных будет иметь какой-либо метод прозрачного кодирования / декодирования для вас и всегда будет давать вам строки Юникода. В противном случае вам нужно будет кодировать / декодировать вручную.
  2. Используйте строки Unicode в вашем приложении.
  3. Прямо перед тем, как двоичные данные покидают ваше приложение, используйте encode() в строке для кодирования в желаемую кодировку.
    • Если ваша целевая кодировка не может представлять некоторые из ваших символов Юникода, вы можете получить UnicodeEncodeError. В этом случае выполните одно из следующих действий:
      1. Используйте второй аргумент для encode(), чтобы игнорировать или заменить символы, которые не могут быть представлены в целевой кодировке;
      2. Не генерируйте эти символы в вашем приложении.
      3. Найдите альтернативный способ их представления. Например, в XML вы можете использовать числовой символьный объект.
    • Для файлов вы можете использовать оболочку codecs.open для прозрачного кодирования.
    • Для соединений с базой данных драйвер часто будет иметь возможность принимать строки в кодировке Юникод и кодировать их для вас.
    • Для сетевых подключений вы обычно должны кодировать вручную. Иногда полезная нагрузка генерируется библиотекой, которая будет правильно кодировать для вас (например, писать XML).
0 голосов
/ 22 января 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...