2017-01-23 4 views
2

было высказано предположение, что этот вопрос является дубликатом 6269765. Я не использовал никаких букв b 'в исходном коде или минимальном. увидеть Внедренный редактирует ниже:str.encode() изменяет символы UTF-8

Я свел проблему я был с сегодня до этого минимального Python 3 кода:

x='\xc3\xb3' 
print(''.join([hex(ord(c))[2:] for c in x])) 
print(''.join([hex(c)[2:] for c in x.encode()])) 

Когда я запускаю этот код я получаю:

c3b3 
c383c2b3 

Действительно ли str.encode() должен менять символ UTF-8 - (ЛАТИНСКОЕ МАЛОЕ ПИСЬМО O С ОСТРОМ) до двух символов ³ (ЛАТИНСКОЕ КАПИТАЛОВОЕ ПИСЬМО A CIRCUMFLEX и SUPERSCRIPT THREE)?


редактировать:

Нет ó был введен как один из комментаторов предложил. Только в некоторых случаях был введен и был прочитан из текстового файла в других. В текстовом файле была оригинальная проблема. Это был системный словарь-файл текущей версии Ubuntu. Файл датирован 23 октября 2011 года и имеет путь к файловой системе, как показано в примерах команд исходного вопроса.

Исходная проблема связана с знаком Asunción в строке 1053 этого файла. Характер ó в Асунсьоне не имеет последовательность байт C3B3, который описан в FileFormat.Info UTF-8 lookup table, как латинская буква О С ОСТРОЙ (как описано здесь для читателей, которые не могут правильно читать текст Unicode.

Нет B «» литералов были использованы в любой код, ни оригинал, ни минимальный.

Характер проблемы был обнаружен как символ UTF, который изменяется от символа ñ до Ã3.Это связано с изменением c3b3 на c383c2b3. Файл словаря буквально содержит два байта c3b3, которые дисплей - как и ожидалось, и как описано в этой таблице UTF-8. Исходная проблема была вызвана исключением из-за изменения длины.

Использование str.encode() было использовано для решения проблемы и поиска его источника. Считается, что что-то, где-то, делало что-то похожее на str.encode().

Минимальный код, чтобы показать эту проблему на первый был:

x='Asunción' 
print(' '.join([hex(ord(c))[2:] for c in x])) 
print(' '.join([hex(c)[2:] for c in x.encode()])) 

, но я обнаружил, что многие люди не смогли увидеть нижний регистр острого о поэтому я изменил его шестнадцатеричных кодов (\ х) который имел тот же шестнадцатеричный контрольный вывод как до , так и после str.encode() в качестве первого минимального примера, приведенного выше, с буквальным полным словом Asunción.

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

конец редактирования, обратно к исходному сообщению:


Это UTF-8 символы встречались в файле словаря американского английском на последнем американском английском Ubuntu издания под названием /usr/share/dict/american-english. Вы можете увидеть первое слово в этом файле с этой последовательностью с помощью следующей команды:

head -1053 /usr/share/dict/american-english|tail -1 

Вы можете увидеть его в шестнадцатеричном формате с помощью команды:

head -1053 /usr/share/dict/american-english|tail -1|od -Ad -tx1 

описания символов были получены из here. Я запускаю Python 3.5.2, скомпилированный на GCC 5.4.0 на Ubuntu 16.04.1 LTS, обновленный 2 дня назад.

редактировать:

правильный ответ здесь, чтобы избежать байтов полностью и не использовать str.encode()? или есть лучший ответ?

+0

Вы ввели символы ³, и Python отдал их вам. Что вы ожидали? –

+0

Возможный дубликат [Что делает символ «b» перед строковым литералом?] (Http://stackoverflow.com/questions/6269765/what-does-the-b-character-do-in-front- of-a-string-literal) –

+0

[Что нового в Python 3.0 - Текст Vs. Данные вместо Unicode Vs. 8-бит] (https://docs.python.org/3/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit) –

ответ

1

Малая д вопрос вырвала из очень большого Q Вопрос:

Когда я запускаю этот код я получаю:

c3b3

c383c2b3

Является str.encode () действительно должен изменить символ UTF-8 - (LATIN МАЛЕНЬКОГО ПИСЬМА O С ОСТРОМ) до двух символов ³ (LATIN CAPITAL LETTER A WITH CIRCUMFLEX и SUPERSCRIPT T HREE)?

Нет такой вещи, как символ «UTF-8». LATIN SMALL LETTER O WITH ACUTE - символ Юникода (объект python: str). Его код Unicode - U + 00F3.

>>> import unicodedata as ucd 
>>> smalloacute = u"\u00f3" 
>>> ucd.name(smalloacute) 
'LATIN SMALL LETTER O WITH ACUTE' 

Теперь вы можете закодировать, что к bytes объекта:

>>> smalloacute.encode('utf8') 
b'\xc3\xb3' 

и писать свои байты объекта в файл или что вы хотите сделать. Обратите внимание, что b'\xc3' является объектом байтов и не имеет полезного отношения к LATIN CAPITAL LETTER A WITH CIRCUMFLEX. Аналогично b'\xb3' и SUPERSCRIPT THREE.

Вы, конечно же, не хотите вращать колесо utf8 во второй раз; результат не очень полезен:

>>> `smalloacute.encode('utf8').decode('latin1').encode('utf8') 
b'\xc3\x83\xc2\xb3'` 

Видел, что раньше? Примечание: decode('latin1') просто меняет тип от bytes до str.

Назад к исходному вопросу/заявлению «str.encode() изменяет символы UTF-8». Короткий ответ: нет, нет! Из файла вы получаете 2-байтную последовательность, представляющую о-острый символ Юникода. Вы можете работать с этим напрямую. В качестве альтернативы вы можете делать байты.декодировать() и работать в str объектах. Вы должны очень точно не делать bytes.kludge().encode().

1

Вам даже не нужно вызывать encode(), чтобы узнать, что находится в вашей строке. Python будет просто показать его вам в интерактивном режиме:

>>> '\xc3\xb3' 
'ó' 

Это строка Юникода, длиной 2, чьи персонажи именно то, что вы видите. Никакие байты или UTF-8 не задействованы вообще, за исключением, возможно, на границе, чтобы отправить их на ваш терминал или прочитать их из исходного файла. Если вам нужен символ юникода в строке, вы можете напрямую вставить его или вывести его с помощью \ x (если FF или меньше), \ u (если FFFF или меньше) или \ U (для всех символов).

>>> '\xf3' == '\u00f3' == 'ó' 
True 

И если вы сделать хотят UTF-8 буквальных по какой-то причине, что было бы байты буквальные:

>>> b'\xc3\xb3' 
b'\xc3\xb3' 

Это строка байт, длины 2. Когда вы спрашиваете Python, чтобы показать его вам, он показывает это как написанный, потому что Python не знает, что находится в ваших байтах.

>>> b'\xc3\xb3'.decode() 
'ó' 

Входной байт является строка (длиной 2, содержащий данные UTF-8), а выход является Юникода строка (длины 1).

 Смежные вопросы

  • Нет связанных вопросов^_^