Как указать расширенный ascii (то есть диапазон (256)) в строке спецификатора магии кодирования питона?

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

## -*- coding: ascii -*-

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

## -*- coding: eascii -*-

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

EDIT:

Здесь дамп оскорбительного раздела файла:

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  |.............]+(|

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

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

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

Спасибо!

Грег

Ответ 1

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

Используйте 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) где-то в своем дизайне. В C тип данных char действительно является байтом. Я видел одну Java 1.4 VM, где конструктор 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!').

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

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

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

Ответ 2

Try

## -*- 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.

Ответ 3

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

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 | токен: 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 e ed ee ef f0 f1 f2 |................ |
00000250 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 5d 2b 28 |.............] + (|

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

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

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