Как указать расширенный 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"