Форум программистов, компьютерный форум, киберфорум
Python
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.93/15: Рейтинг темы: голосов - 15, средняя оценка - 4.93
быдлокодер
1718 / 905 / 106
Регистрация: 04.06.2008
Сообщений: 5,612
1

Код не выводит символы в кодировке UTF-8, которые представляют из себя суррогатные пары юникода

14.10.2016, 20:06. Просмотров 2899. Ответов 10
Метки нет (Все метки)

Друзья! Продолжаем разбираться с юникодом .Вот код. Он должен выводить таблицу юникода, точнее первые 65535 символов.

тут код
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/usr/bin/env python3
# Copyright (c) 2008 Qtrac Ltd. All rights reserved.
# This program or module is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. It is provided for educational
# purposes and is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
 
import sys
import unicodedata
 
 
def print_unicode_table(word):
    print("decimal   hex   chr  {0:^40}".format("name"))
    print("-------  -----  ---  {0:-<40}".format(""))
 
    code = ord(" ")
    end = sys.maxunicode
 
    print (code, end)
 
    while code < end:
        c = chr(code)
        name = unicodedata.name(c, "*** unknown ***")
        if word is None or word in name.lower():
            print("{0:7}  {0:5X}  {0:^3c}  {1}".format(
                  code, name.title()))
        code += 1
 
 
word = None
if len(sys.argv) > 1:
    if sys.argv[1] in ("-h", "--help"):
        print("usage: {0} [string]".format(sys.argv[0]))
        word = 0
    else:
        word = sys.argv[1].lower()
if word != 0:
    print_unicode_table(word)



Вот когда он доходит до символа с номером 0XD800, выдаёт такую ошибку:

Windows Batch file
1
2
3
4
5
6
Traceback (most recent call last):
  File "E:/.../print_unicode_0.py", line 42, in <module>
    print_unicode_table(word)
  File "E:/.../print_unicode_0.py", line 30, in print_unicode_table
    code, name.title()))
UnicodeEncodeError: 'utf-8' codec can't encode character '\ud800' in position 17: surrogates not allowed
Наверное, это так надо. Наверное, символы с 0xD800 по DFFF включительно это какие-то хитрые суррогатные пары, с которыми я не до конца разобрался и так всё и должно работать (то есть не работать).

Но дело в том, что этот код идёт приложением к этой книге; файл называется print_unicode.py
Вряд ли её автор Марк Саммерфилд ошибся. Поэтому, ошибся, скорее всего, я. Как же мне вывести ВСЕ СИМВОЛЫ, в том числе и с 0xD800 по DFFF? Спасибо, кто откликнется. Питон 3.1.1
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.10.2016, 20:06
Ответы с готовыми решениями:

Неправильно отображает в файле символы в кодировке UTF-8
Добрый день. Нужна помощь. Есть текстовый файл (в нем содержится фрагмент таблицы cp437), который...

Как получить код символа в кодировке UTF-8?
Имеется WP. В нем посты в кодировке UTF-8. Как получить код символа в кодировке UTF-8? Вообще...

Дан символьный массив. Найти символы, которые представляют собой цифры
Дан символьный массив. В нем надо найти такие символы, которые представляют собой цифры. То есть...

Код выводит сам себя
Как сделать так, чтобы прога выводила свой код. Т.е саму себя

10
373 / 257 / 71
Регистрация: 03.12.2015
Сообщений: 576
17.10.2016, 16:30 2
Цитата Сообщение от kravam Посмотреть сообщение
Наверное, это так надо. Наверное, символы с 0xD800 по DFFF включительно это какие-то хитрые суррогатные пары, с которыми я не до конца разобрался и так всё и должно работать (то есть не работать).
Символы с 0xD800 по 0xDFFF не являются обычными символами юникода. Эти "символы" являются управляющими конструкциями, которые нужны для того, чтобы представлять символы юникода сверх стандартных 0xFFFF (с 0x10000 по 0x10FFFF). Каждая суррогатная пара представляет собой один символ юникода сверх 0xFFFF (можно закодироваться свыше миллиона дополнительных символов). Для совместимости сделано.

В общем, вывести символы с такими кодами не получится, их просто не существует.

Обрабатывать в питоне такие коды можно. Нужно передавать в encode и decode параметр 'surrogatepass', иначе будет выдавать ошибку.
Python
1
mystring.encode("utf-16", "surrogatepass").decode("utf-16", "surrogatepass")
См. https://docs.python.org/3/library/codecs.html
2
быдлокодер
1718 / 905 / 106
Регистрация: 04.06.2008
Сообщений: 5,612
18.10.2016, 17:28  [ТС] 3
Что понял: суррогатные пары нужны.

К примеру, у нас есть символ юникода 0X1024FF

Задача 1:
символ юникода 0X1024FF нужно представить в кодировке UTF-16

Используем алгоритм, описанный здесь. Используем также суррогатные пары. Получаем число
0XDBC9DCFF

++++++++++++++++++++++++++++++++++++++++++

Задача 2:
символ юникода 0X1024FF нужно представить в кодировке UTF-8:

Вот UTF-8 использует суррогатные пары для кодирования? По-моему, нет. По-моему, он, встретив числа, из диапазонов 0xD800 - 0xDFFF, просто бьёт тревогу (выкидывает исключение или что-то в этом роде). Числа из указанного диапазона для utf-8 как аппендицит. Хочу это уточнить.

Ну и чтобы уж добить задачу, я бы закодировал как описано здесь и получил бы 0XF48293BF
0
2714 / 2318 / 620
Регистрация: 19.03.2012
Сообщений: 8,832
18.10.2016, 17:47 4
http://stackoverflow.com/quest... t-encode-s
0
быдлокодер
1718 / 905 / 106
Регистрация: 04.06.2008
Сообщений: 5,612
18.10.2016, 22:06  [ТС] 5
alex925, по ссыли, что вы мне дали, написано:

They used partial surrogates to encode the 'bad' bytes, but the normal UTF8 encoder can't handle them when printing to the terminal.
, было бы вам благодарен, если бы вы сказали это просто своими словами и всё.

То есть не работает UTF-8 с суррогатными парами.

++++++++++++++++++++++++++++++++++++++++++++++

vrm2, а позвольте спросить, вот вы привели часть кода. А я вот этот код упростил:

Python
1
2
3
4
>>> "\U00010155".encode("utf-16")
b'\xff\xfe\x00\xd8U\xdd'
>>> "\U00010155".encode("utf-16", "surrogatepass")
b'\xff\xfe\x00\xd8U\xdd'
Выводы одинаковы во втором случае я использовал "surrogatepass" на всякий случай. Хочется спросить- это чего вообще? Если это кодирование символа U+10155, то это неправильное какое-то кодирование. Тут написано, что должно получиться. То есть результат должен быть 4 байта:
D8 00 DD 55 или 00 D8 55 DD, в зависимости от порядка байт.

То есть как-то так:
Python
1
b'\xDD\x00\xDD\x55'
а не то, что получилось.
0
373 / 257 / 71
Регистрация: 03.12.2015
Сообщений: 576
19.10.2016, 00:02 6
Цитата Сообщение от kravam Посмотреть сообщение
Если это кодирование символа U+10155, то это неправильное какое-то кодирование. Тут написано, что должно получиться. То есть результат должен быть 4 байта:
D8 00 DD 55 или 00 D8 55 DD, в зависимости от порядка байт.
Так как раз и получается 00 D8 55 DD (b'\xff\xfe\x00\xd8U\xdd'), если учесть что U это '\x55'.
В начале стоит "\xff\xfe" - указание на utf-16le.

Python
1
2
3
4
5
6
>>> '\U00010155'.encode("utf-16be").hex()
'd800dd55'
>>> '\U00010155'.encode("utf-16le").hex()
'00d855dd'
>>> '\U00010155'.encode("utf-16").hex()
'fffe00d855dd'
0
2714 / 2318 / 620
Регистрация: 19.03.2012
Сообщений: 8,832
19.10.2016, 00:30 7
kravam, Ну написано же, что сурогаты используются как вспомогательные символы, а в чистом виде не используются.
0
быдлокодер
1718 / 905 / 106
Регистрация: 04.06.2008
Сообщений: 5,612
21.10.2016, 16:49  [ТС] 8
Цитата Сообщение от vrm2 Посмотреть сообщение
Python
1
2
>>> '\U00010155'.encode("utf-16be").hex() 
'd800dd55'
прежде чем, пойти дальше хочется спросить- как вы добились такого эффекта? Мой интерпретатор пишет:

Python
1
2
3
4
>>> '\U00010155'.encode("utf-16be").hex()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'bytes' object has no attribute 'hex'
у меня питон 3.1.1
0
373 / 257 / 71
Регистрация: 03.12.2015
Сообщений: 576
21.10.2016, 18:41 9
Цитата Сообщение от kravam Посмотреть сообщение
прежде чем, пойти дальше хочется спросить- как вы добились такого эффекта?
Метод hex доступен начиная с версии 3.5. В старых версиях используйте другой способ. См. http://stackoverflow.com/quest... n-python-3.
0
быдлокодер
1718 / 905 / 106
Регистрация: 04.06.2008
Сообщений: 5,612
28.10.2016, 16:59  [ТС] 10
Уточним некоторые детали.
Цитата Сообщение от vrm2 Посмотреть сообщение
Обрабатывать в питоне такие коды можно. Нужно передавать в encode и decode параметр 'surrogatepass', иначе будет выдавать ошибку.

Python
1
mystring.encode("utf-16", "surrogatepass").decode("utf-16", "surrogatepass")
Вот не знаю, зачем тут указывать "surrogatepass", мне кажется, параметр "utf-16"однозначно указывает, как интерпретировать строку, то есть: "если встретилось число, старший байт которого, D8, не удивляться и обрабатывать как суррогатную пару", то есть указание "utf-16" УЖЕ предполагает суррогатную пару. "utf-8", например, не предполагает, а "utf-16" предполагает

Тем более, что вот код делает то же, что у вас, показывает нам закодированную строку из одного символа. Видно, что там есть суррогатные пары, потом её декодирует и выводит её (выводит числовое значение символа). Только я для наглядности разбил код на стадии. Вполне себе корректно обрабатывает суррогатные пары и без явного указания, что они есть.

Python
1
2
3
4
5
6
7
>>> s = "\U001024Ff"
>>> x = s.encode("utf-16")
>>> x
b'\xff\xfe\xc9\xdb\xff\xdc'
>>> s = x.decode("utf-16")
>>> hex (ord(s))
'0x1024ff'
0
Почетный модератор
Эксперт по компьютерным сетямЭксперт Windows
28007 / 15733 / 971
Регистрация: 15.09.2009
Сообщений: 67,816
Записей в блоге: 78
04.04.2017, 21:16 11
как то так
0
Миниатюры
Код не выводит символы в кодировке UTF-8, которые представляют из себя суррогатные пары юникода  
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.04.2017, 21:16

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Что представляют из себя данные WAV?
Доброго времени. Мой вопрос может показаться дилетантским, и что на него можно ответить &quot;данные...

Что из себя представляют базы данных
Прошу прощение за свое невежество, но есть вопрос следующего характера: пытаясь понять, что собой...

Что из себя представляют типы данных?
Всем привет! Изучаю С++ по книге Шилда Г.С... Прошел тему по Типам данных в С++ и двигаюись...

Что из себя представляют XPS-файлы?
Сколько имею ПК никогда не сталкивался с файлами XPS. Что это. Можно ли отключить в компонентах...

Что из себя представляют базовые средства языка?
в билете к экзамену есть такой вопрос....про что здесь нужно отвечать??:help:?

соханение в бокнот в кодировке UTF-8
if SaveTextFileDialog1.Execute then Memo1.Text := AnsiToUtf8(Memo1.Text); ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.