Как мне указать расширенный ASCII (т.е. диапазон (256)) в строке спецификатора магического кодирования Python? - PullRequest
10 голосов
/ 28 июля 2011

Я использую шаблоны mako для создания специализированных конфигурационных файлов.Некоторые из этих файлов содержат расширенные символы ASCII (> 127), но мако-дроссели говорят, что символы не входят в диапазон, когда я использую:

## -*- coding: ascii -*-

Так что мне интересно, возможно, есть что-то вроде:

## -*- coding: eascii -*-

То, что я могу использовать, будет в порядке с диапазоном (128, 256) символов.

РЕДАКТИРОВАТЬ:

Вот дамп поврежденного раздела файла:

000001b0  39 c0 c1 c2 c3 c4 c5 c6  c7 c8 c9 ca cb cc cd ce  |9...............|
000001c0  cf d0 d1 d2 d3 d4 d5 d6  d7 d8 d9 da db dc dd de  |................|
000001d0  df e0 e1 e2 e3 e4 e5 e6  e7 e8 e9 ea eb ec ed ee  |................|
000001e0  ef f0 f1 f2 f3 f4 f5 f6  f7 f8 f9 fa fb fc fd fe  |................|
000001f0  ff 5d 2b 28 27 73 29 3f  22 0a 20 20 20 20 20 20  |.]+('s)?".      |
00000200  20 20 74 6f 6b 65 6e 3a  20 57 4f 52 44 20 20 20  |  token: WORD   |
00000210  20 20 22 5b 41 2d 5a 61  2d 7a 30 2d 39 c0 c1 c2  |  "[A-Za-z0-9...|
00000220  c3 c4 c5 c6 c7 c8 c9 ca  cb cc cd ce cf d0 d1 d2  |................|
00000230  d3 d4 d5 d6 d7 d8 d9 da  db dc dd de df e0 e1 e2  |................|
00000240  e3 e4 e5 e6 e7 e8 e9 ea  eb ec ed ee ef f0 f1 f2  |................|
00000250  f3 f4 f5 f6 f7 f8 f9 fa  fb fc fd fe ff 5d 2b 28  |.............]+(|

Первый персонаж, на которого жалуется Мако, - 000001b4.Если я удаляю этот раздел, все работает нормально.Со вставленным разделом Мако жалуется:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 19: ordinal not in range(128)

Это та же самая жалоба, использую ли я 'ascii' или 'latin-1' в строке волшебного комментария.

Спасибо!

Грег

Ответы [ 3 ]

15 голосов
/ 28 июля 2011

Краткий ответ

Используйте cp437 в качестве кодировки для некоторого ретро-развлечения для DOS. Все байтовые значения, большие или равные 32 десятичным, кроме 127, отображаются в отображаемые символы в этой кодировке. Затем используйте cp037 в качестве кодировки для действительно трипового времени. А затем спросите себя, как вы действительно знаете, какой из них, если какой-либо из них, является «правильным».

Длинный ответ

Есть кое-что, что вы должны отучить: абсолютная эквивалентность байтовых значений и символов.

Многие основные текстовые редакторы и средства отладки сегодня, а также спецификация языка Python подразумевают абсолютную эквивалентность между байтами и символами, хотя в действительности их не существует. Неверно, что 74 6f 6b 65 6e является"токеном". Это соответствие действительно только для ASCII-совместимых кодировок символов. В EBCDIC, который все еще довольно распространен сегодня, «токен» соответствует байтовым значениям a3 96 92 85 95.

Поэтому, хотя интерпретатор Python 2.6 с радостью оценивает 'text' == u'text' как True, этого не следует делать, поскольку они только эквивалентны в предположении ASCII или совместимой кодировки, и даже тогда они должны не считается равно . (По крайней мере, '\xfd' == u'\xfd' - это False и вы получите предупреждение за попытку.) Python 3.1 оценивает 'text' == b'text' как False. Но даже принятие этого выражения интерпретатором подразумевает абсолютную эквивалентность байтовых значений и символов, потому что выражение b'text' используется для обозначения «строки байтов, которую вы получаете, когда применяете кодировку ASCII к 'text'» с помощью переводчик.

Насколько я знаю, каждый широко распространенный сегодня язык программирования подразумевает неявное использование кодировки символов ASCII или ISO-8859-1 (Latin-1) где-то в своем дизайне. В Си тип данных char действительно является байтом. Я видел одну виртуальную машину Java 1.4, где конструктор java.lang.String(byte[] data) предполагал кодировку ISO-8859-1. Большинство компиляторов и интерпретаторов допускают кодирование исходного кода в кодировке ASCII или ISO-8859-1 (некоторые позволяют вам его изменить). В Java длина строки действительно равна длине кодовой единицы UTF-16, что, возможно, неправильно для символов U+10000 и выше. В Unix имена файлов - это байтовые строки, интерпретируемые в соответствии с настройками терминала, что позволяет вам open('a\x08b', 'w').write('Say my name!').

Итак, мы все были обучены и обусловлены инструментами, которым мы научились доверять, полагая, что «А» - это 0x41. Но это не так. «A» - это символ, а 0x41 - это байт, и они просто не равны.

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

PS: фразы "расширенный ASCII" и "набор символов ANSI" являются неправильными.

2 голосов
/ 28 июля 2011

Попробуйте

## -*- coding: UTF-8 -*-

или

## -*- coding: latin-1 -*-

или

## -*- coding: cp1252 -*-

в зависимости от того, что вам действительно нужно.Последние два аналогичны, за исключением:

Кодовая страница Windows-1252 совпадает с ISO-8859-1 для всех кодов, кроме диапазона от 128 до 159 (шестнадцатеричные от 80 до 9F), где мало используется C1элементы управления заменены на дополнительные символы.Windows-28591 является действительной кодовой страницей ISO-8859-1.

, где ISO-8859-1 является официальным названием latin-1.

1 голос
/ 28 июля 2011

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

000001b0 39 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce | 9 ............... |
000001c0 cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 да db dc dd de | ................ |
000001d0 df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ee | ................ |
000001e0 ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe | ................ |
000001f0 ff 5d 2b 28 27 73 29 3f 22 0a 20 20 20 20 20 20 |.] + (S)? ". |
00000200 20 20 74 6f 6b 65 6e 3a 20 57 4f 52 44 20 20 20 | токен: WORD |
00000210 20 20 22 5b 41 2d 5a 61 2d 7a 30 2d 39 c0 c1 c2 | «[A-Za-z0-9 ... |
00000220 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 | ................ |
00000230 d3 d4 d5 d6 d7 d8 d9 да db dc dd de df e0 e1 e2 | ................ |
00000240 e3 e4 e5 e6 e7 e8 e9 eab e efe ef f0 f1 f2 | ................ |
00000250 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd ff fe ff 5d 2b 28 | .............] + (|

Материал, выделенный жирным шрифтом, состоит из двух частей (каждый байт от 0xc0 до 0xff включительно). Похоже, у вас есть двоичный файл (возможно, дамп скомпилированного регулярного выражения), а не текстовый файл. Я предлагаю вам прочитать его как двоичный файл, а не вставлять его в исходный файл Python. Вам также следует прочитать документы mako, чтобы узнать, чего они ожидают.

Обновление после просмотра текстовой части вашего дампа: вы вполне можете выразить это в регулярных выражениях только для ASCII, например у вас будет строка, содержащая

token: WORD "[A-Za-z0-9\xc0-\xff]+(etc)etc"
...