Python3: печатать текст с смайликами, прочитанными из текстового файла с не ASCII-символами (unicode_escape) - PullRequest
0 голосов
/ 24 апреля 2020

Я хочу прочитать строки текстового файла, которые содержат эмодзи и не-ASCII-символы, и, наконец, распечатать их. Проблема в том, что я могу либо правильно печатать глиф эмодзи, либо не ASCII-символ (например, ü).

Строка в текстовом файле (в формате UTF-8):

Я устал. - Ich bin müde \ U0001F4A4

Код для чтения:

with open(path_txt,"r", encoding="unicode_escape") as file:
    content = file.readlines()
    print(content[0])
  1. При кодировании = "unicode_escape" я получаю смайлики сна и некоторые символы crypti c для тебя".
  2. При кодировке = "utf-8" (или по умолчанию) она печатает последовательность Unicode \ U0001F4A4 для смайликов и правильное "ü". Во втором случае \ U ... получает двойной выход в \ U. Я думаю, str.replace ("\ U", "\ U") может быть временным решением, но ОШИБКА:

код 'unicodeescape' c не может декодировать байты в позиции 0 -1: усеченный \ UXXXXXXXX escape

Я также попробовал encoding = "raw_unicode_escape". Как новичок, я не понимаю весь юникод topi c. Спасибо за вашу помощь / обходные пути !!

Похожая / та же проблема здесь (04/2014): https://bugs.python.org/issue21331

1 Ответ

1 голос
/ 25 апреля 2020

Кажется, что содержимое состоит из некоторой смеси escape-символов (для эмодзи) и символов в кодировке UTF-8 (для "ü").

Это не совсем ясно из вашего поста, но я предполагаю, если вы прочитаете файл в двоичном режиме (open(path, 'rb')) и напечатаете первую строку, вы увидите это:

b'm\xc3\xbcde \\U0001f4a4'

Это означает, что «ü» был закодирован в UTF-8, но смайлики сбежал. Примечание. Вы также видите escape-последовательности для «ü», но это только представление. Попробуйте len(b'\xc3'), и вы увидите, что на самом деле это строка длиной 1 байт. b'\\U0001f4a4' с другой стороны - действительно escape-последовательность длиной 10.

Теперь последовательность «unicode-escape» не ожидает именно этого формата. Он интерпретирует неэкранированные не-ASCII символы как Latin-1 - поэтому при использовании этого кода вы видите искаженные символы вместо «ü» c:

>>> b'm\xc3\xbcde \\U0001f4a4'.decode('unicode-escape')
'müde ?'

Но если для «unicode-escape» требуется латиница - 1, мы можем дать это! Во-первых, мы декодируем с помощью UTF-8, чтобы получить «ü» правильно:

>>> b'm\xc3\xbcde \\U0001f4a4'.decode('utf8')
'müde \\U0001f4a4'

Это не касается побега эмодзи, поскольку все это ASCII. Символы из диапазона ASCII кодируются одинаково для Latin-1 и UTF-8 (и ASCII).

Теперь мы кодируем с Latin-1:

>>> b'm\xc3\xbcde \\U0001f4a4'.decode('utf8').encode('latin1')
b'm\xfcde \\U0001f4a4'

, и это что-то " Unicode-escape "код c понимает:

>>> b'm\xc3\xbcde \\U0001f4a4'.decode('utf8').encode('latin1').decode('unicode-escape')
'müde ?'

В вашей настройке вы можете отложить первый decode шаг до внутренней обработки open():

with open(path_txt, "r", encoding="utf-8") as file:
    for line in file:
        line = line.encode('latin1').decode('unicode-escape')
        # do something with line
...