Каков надежный способ преобразовать некоторую строку (utf-8 или другое) в простую строку ASCII в python

StackOverflow https://stackoverflow.com/questions/1792602

  •  22-09-2019
  •  | 
  •  

Вопрос

Внутри моего скрипта python я получаю некоторую строку обратно из функции, которую я не писал.Его кодировка варьируется.Мне нужно преобразовать его в формат ascii.Есть ли какой-нибудь надежный способ сделать это?Я не возражаю заменить символы, отличные от ascii, пробелами или чем-то еще...

Это было полезно?

Решение

Если вам нужна строка ASCII, которая однозначно представляет то, что у вас есть, без потери какой-либо информации, ответ прост:

Не возитесь с кодированием / декодированием, используйте repr() функция (Python 2.X) или ascii() функция (Python 3.x).

Другие советы

Вы говорите "его кодировка меняется".Я предполагаю, что под "этим" вы подразумеваете "строку" Python 2.x, которая на самом деле представляет собой последовательность байтов.

Ответ на часть первую:если вы не знаете кодировку этой закодированной строки, то НЕТ, вообще нет никакого способа сделать с этим что-либо значимое *.Если вы делай знайте кодировку, затем первым шагом будет преобразование вашего str в unicode:

encoded_string = i_have_no_control()
the_encoding = 'utf-8' # for the sake of example
text = unicode(encoded_string, the_encoding)

Затем вы можете перекодировать свой объект unicode в ASCII, если хотите.

ascii_garbage = text.encode('ascii', 'replace')

* Существуют эвристические методы для угадывания кодировок, но они медленные и ненадежные.Вот одна отличная попытка на Python.

Я бы попытался нормализовать строку, а затем закодировать ее.О чем :

import unicodedata
s = u"éèêàùçÇ"
print unicodedata.normalize('NFKD',s).encode('ascii','ignore')

Это работает, только если у вас есть юникод в качестве входных данных. Поэтому вы должны знать, что можно сделать с кодированием выходных данных функции, и декодировать ее.Если вы этого не сделаете, то существуют эвристики обнаружения кодировки, но для коротких строк они ненадежны.

Конечно, тебе могла бы повезти и выходные данные функции зависят от различных неизвестных кодировок, но используют ascii в качестве кодовой базы, поэтому они будут выделять одно и то же значение для байтов от 0 до 127 (например, utf-8).

В этом случае вы можете просто избавиться от нежелательных символов, отфильтровав их с помощью Упорядоченные наборы :

import string.printable # asccii chars
print "".join(OrderedSet(string.printable) & OrderedSet(s))

Или, если вы хотите вместо этого заготовки :

print("".join(((char if char in  string.printable else " ") for char in s )))

"translate" может помочь вам сделать то же самое.

Единственный способ узнать, так ли вам повезло, - это попробовать это...Иногда большой счастливый день - это то, что нужно любому разработчику :-)

Что подразумевается под "надежностью", так это то, что функция не завершается сбоем даже при самом неясном, невозможном вводе - это означает, что вы могли бы передать функции случайные двоичные данные, и ОНА НИКОГДА НЕ ЗАВЕРШИЛАСЬ БЫ СБОЕМ, НЕСМОТРЯ НИ НА ЧТО.Вот что значит "надежный".

Затем функция должна продолжить делать все возможное, чтобы преобразовать в целевую кодировку.Если ему приходится выбрасывать весь мусор, которого он не понимает, то это совершенно нормально и на самом деле является наиболее желаемым результатом.Зачем пытаться спасти весь этот хлам?Просто выбросьте мусор.Скажите пользователю, что он не просто придурок из-за использования чего-либо Microsoft, но и нестандартный придурок из-за использования чего-либо нестандартного Microsoft ... или за попытку отправки двоичных данных!

У меня точно такая же потребность (хотя моя потребность в PHP), и у меня также есть пользователи, которые, по крайней мере, такие же идиоты, как и я, иногда даже больше;тем не менее, они определенно приятнее и, без сомнения, терпеливее.

Лучшее, что я нашел на данный момент, - это (в PHP 5.3):

$fixed_string = iconv( 'ISO-8859-1', 'UTF-8//ИГНОРИРОВАТЬ//ПЕРЕВЕСТИ', $in_string );

Это пытается перевести все, что может, и просто выбрасывает весь мусор, в результате чего получается легальная строка UTF-8.Я также не смог сломать его, вызвать сбой или отклонить какой-либо входящий текст или данные, даже скармливая ему кучу бинарных ненужных данных.

Найти iconv() и заставить его работать несложно;что настолько сводит с ума и расточительно, так это чтение всего этого полного мусора и идиотизма, который так много программистов, похоже, поддерживают, когда имеют дело с этим фиаско кодирования.Что стало с завидным (и респектабельным) менталитетом "Бей и сжигай идиотов" старой школы программирования?Давайте вернемся к основам.Используй iconv() и выбрасывай их мусор, и не стесняйся, говоря им, что ты выбросил их мусор - короче говоря, не переставай молотить дебилов, которые кормят тебя мусором.И ты можешь сказать им, что я тебе об этом говорил.

Если все, что вы хотите сделать, это сохранить символы, совместимые с ASCII, и выбросить остальные, то в большинстве кодировок это сводится к удалению всех символов, которые имеют высокий бит set - то есть символы со значением более 127.Это работает, потому что почти все наборы символов являются расширениями 7-битного ASCII.

Если это Нормальный строка (т.е. не unicode), вам необходимо декодировать это в произвольном наборе символов (например, iso-8859-1 поскольку он принимает любые байтовые значения), а затем кодирует в ascii, используя ignore или replace опция для ошибок:

>>> orig = '1ä2äö3öü4ü'
>>> orig.decode('iso-8859-1').encode('ascii', 'ignore')
'1234'
>>> orig.decode('iso-8859-1').encode('ascii', 'replace')
'1??2????3????4??'

Шаг декодирования необходим, потому что вам нужен юникод строка для того, чтобы использовать encode.Если у вас уже есть строка в Юникоде, все проще:

>>> orig = u'1ä2äö3öü4ü'
>>> orig.encode('ascii', 'ignore')
'1234'
>>> orig.encode('ascii', 'replace')
'1??2????3????4??'
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top