Как преобразовать формат файла из Unicode в ASCII с помощью Python?

Я использую сторонний инструмент, который выводит файл в формате Unicode. Однако я предпочитаю, чтобы это было в ASCII. В инструменте нет настроек для изменения формата файла.

Как лучше всего преобразовать весь формат файла с помощью Python?


person Ray    schedule 06.10.2008    source источник


Ответы (8)


Вы можете легко преобразовать файл, просто используя функцию unicode, но вы столкнетесь с проблемами с символами Unicode без прямого эквивалента ASCII.

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

>>> title = u"Klüft skräms inför på fédéral électoral große"

обычно конвертируется в

Klft skrms infr p fdral lectoral groe

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

>>> import unicodedata
>>> unicodedata.normalize('NFKD', title).encode('ascii','ignore')
'Kluft skrams infor pa federal electoral groe'
person ConroyP    schedule 06.10.2008
comment
Это довольно хорошо, за исключением того, что (как уже отмечалось) в нем не хватает нескольких символов. Для Latin-1 вам нужно использовать специальный регистр Æ, Ð, Ø, Þ, æ, ð, ø, ß и þ. - person giltay; 06.10.2008
comment
Об этом сообщил Фредрик Лунд с простым скриптом, который можно построить поверх unicodedata для замены в особых случаях: effbot.org/zone/unicode-convert.htm - person rcoup; 18.04.2012

Я думаю, что это более серьезная проблема, чем вы думаете. Просто изменить файл из Unicode в ASCII легко, однако получить перевод всех символов Unicode в разумные эквиваленты ASCII (многие буквы недоступны в обеих кодировках) - другое.

Это руководство по Python Unicode может дать вам лучшее представление о том, что происходит со строками Unicode, переведенными в ASCII: http://www.reportlab.com/i18n/python_unicode_tutorial.html

Вот полезная цитата с сайта:

Python 1.6 также имеет встроенную функцию unicode, для которой вы можете указать кодировку:

> >>> unicode('hello') u'hello'
> >>> unicode('hello', 'ascii') u'hello'
> >>> unicode('hello', 'iso-8859-1') u'hello'
> >>>

Все три из них возвращают одно и то же, поскольку символы в «Hello» являются общими для всех трех кодировок.

Теперь давайте закодируем что-нибудь с европейским акцентом, что выходит за рамки ASCII. То, что вы видите на консоли, может зависеть от языкового стандарта вашей операционной системы; Windows позволяет мне вводить ISO-Latin-1.

> >>> a = unicode('André','latin-1')
> >>> a u'Andr\202'

Если вы не можете ввести острую букву e, вы можете ввести строку «Andr \ 202», что однозначно.

Unicode поддерживает все стандартные операции, такие как итерация и разделение. Мы их здесь не наезжаем.

person Pete Karl II    schedule 06.10.2008
comment
Спасибо, что указали на потенциальные проблемы. Однако я не рискую иметь неконвертируемые символы Юникода в содержимом выходного файла. Он просто выводит схему SQL внутренней базы данных и не содержит никаких необычных символов, то есть за пределами ASCII. - person Ray; 06.10.2008
comment
@ Рэй Вега: Это ты сейчас знаешь. Предполагать, что данные Unicode будут содержать только символы ASCII, является ошибкой и потенциальной ошибкой. - person Robert P; 01.09.2011

Между прочим, это команда Linux iconv для выполнения такой работы.

iconv -f utf8 -t ascii <input.txt >output.txt
person kev    schedule 17.12.2011

Вот простой (и глупый) код для перевода кодировки. Я предполагаю (но вы не должны), что входной файл находится в UTF-16 (Windows называет это просто «Unicode»).

input_codec = 'UTF-16'
output_codec = 'ASCII'

unicode_file = open('filename')
unicode_data = unicode_file.read().decode(input_codec)
ascii_file = open('new filename', 'w')
ascii_file.write(unicode_data.write(unicode_data.encode(output_codec)))

Обратите внимание, что это не сработает, если в файле Unicode есть какие-либо символы, которые не являются также символами ASCII. Чтобы превратить нераспознанные символы в символы "?", Можно сделать следующее:

ascii_file.write(unicode_data.write(unicode_data.encode(output_codec, 'replace')))

Более простой выбор см. В документации. Если вам нужно сделать что-то более сложное, вы можете попробовать UNICODE Hammer на Поваренная книга Python.

person giltay    schedule 06.10.2008

Нравится:

uc = open(filename).read().decode('utf8')
ascii = uc.decode('ascii')

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

РЕДАКТИРОВАТЬ: Как только что указал Пит Карл, нет однозначного сопоставления от Unicode до ASCII. Поэтому некоторые символы просто невозможно преобразовать таким образом, чтобы сохранить информацию. Более того, стандартный ASCII является более или менее подмножеством UTF-8, поэтому вам даже не нужно делать какое-либо декодирование.

person Dan Lenski    schedule 06.10.2008

Для моей проблемы, когда я просто хотел пропустить символы, отличные от ascii, и просто выводить только вывод ascii, приведенное ниже решение сработало очень хорошо:

    import unicodedata
    input = open(filename).read().decode('UTF-16')
    output = unicodedata.normalize('NFKD', input).encode('ASCII', 'ignore')
person Vijay    schedule 10.06.2011

Важно отметить, что формата файлов Unicode не существует. Юникод можно закодировать в байты несколькими способами. Чаще всего UTF-8 или UTF-16. Вам нужно знать, какой из них выводит ваш сторонний инструмент. Как только вы это узнаете, конвертировать между разными кодировками довольно просто:

in_file = open("myfile.txt", "rb")
out_file = open("mynewfile.txt", "wb")

in_byte_string = in_file.read()
unicode_string = bytestring.decode('UTF-16')
out_byte_string = unicode_string.encode('ASCII')

out_file.write(out_byte_string)
out_file.close()

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

person Jerry Hill    schedule 06.10.2008

Как отмечали другие плакаты, ASCII - это подмножество юникода.

Однако если вы:

  • иметь устаревшее приложение
  • вы не контролируете код для этого приложения
  • вы уверены, что ваш ввод относится к подмножеству ASCII

В приведенном ниже примере показано, как это сделать:

mystring = u'bar'
type(mystring)
    <type 'unicode'>

myasciistring = (mystring.encode('ASCII'))
type(myasciistring)
    <type 'str'>
person mikemaccana    schedule 15.12.2009