Как мне преобразовать формат файла из Unicode в ASCII с помощью Python?
Вопрос
Я использую сторонний инструмент, который выводит файл в формате Unicode.Однако я предпочитаю, чтобы это было в формате ASCII.Инструмент не имеет настроек для изменения формата файла.
Каков наилучший способ преобразовать весь формат файла с помощью Python?
Решение
Вы можете достаточно легко преобразовать файл, просто используя 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'
Другие советы
Я думаю, что это более глубокая проблема, чем вы думаете . Простое изменение файла из Unicode в ASCII легко, однако, получить все символы Unicode для преобразования в приемлемые аналоги ASCII (многие буквы недоступны в обеих кодировках) - это другое.
Это руководство по Python Unicode может дать вам лучшее представление о том, что происходит со строками Unicode, которые переводятся в ASCII: http://www.reportlab.com/i18n/python_unicode_tutorial.html
Вот полезная цитата с сайта:
Python 1.6 также получает "Юникод" встроенная функция, к которой вы можете укажите кодировку:
> >>> unicode('hello') u'hello'
> >>> unicode('hello', 'ascii') u'hello'
> >>> unicode('hello', 'iso-8859-1') u'hello'
> >>>
Все три из них возвращают одинаковые вещь, так как символы в «Привет» являются общими для всех трех кодировок.
Теперь давайте закодируем что-то Европейский акцент, который находится за пределами ASCII. То, что вы видите на консоли, может зависит от вашей операционной системы локали; Windows позволяет мне печатать ISO-Latin-1.
> >>> a = unicode('André','latin-1')
> >>> a u'Andr\202'
Если вы не можете набрать острую букву е, Вы можете ввести строку «Andr \ 202», что однозначно.
Юникод поддерживает все общее такие операции, как итерация и расщепление. Мы не будем на них бегать здесь.
Кстати, это команда linux iconv
, которая выполняет эту работу.
iconv -f utf8 -t ascii <input.txt >output.txt
Вот простой (и глупый) код для перевода кодировки. Я предполагаю (но вы не должны), что входной файл находится в UTF-16 (Windows называет это просто «Юникод»).
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 по адресу поваренная книга Python.
Вот так:
uc = open(filename).read().decode('utf8')
ascii = uc.decode('ascii')
Однако обратите внимание, что это завершится неудачей с исключением UnicodeDecodeError
, если есть какие-либо символы, которые нельзя преобразовать в ASCII.
РЕДАКТИРОВАТЬ: Как только что отметил Пит Карл, не существует однозначного отображения из Unicode в ASCII. Поэтому некоторые символы просто не могут быть преобразованы в способ сохранения информации. Более того, стандартный ASCII является более или менее подмножеством UTF-8, поэтому вам даже не нужно ничего декодировать.
Для моей проблемы, когда я просто хотел пропустить символы не-ascii и просто выводить только вывод ascii, приведенное ниже решение сработало очень хорошо:
import unicodedata
input = open(filename).read().decode('UTF-16')
output = unicodedata.normalize('NFKD', input).encode('ASCII', 'ignore')
Важно отметить, что отсутствует формат файла '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()
Как отмечалось в других ответах, вы, вероятно, захотите предоставить обработчик ошибок для метода кодирования. Использовать 'replace' в качестве обработчика ошибок очень просто, но он искажает ваш текст, если он содержит символы, которые не могут быть представлены в ASCII.
Как отмечали другие постеры, ASCII является подмножеством unicode.
Однако, если вы:
- у вас есть устаревшее приложение
- вы не контролируете код для этого приложения
- вы уверены, что ваш ввод попадает в подмножество ASCII
Тогда приведенный ниже пример показывает, как это сделать:
mystring = u'bar'
type(mystring)
<type 'unicode'>
myasciistring = (mystring.encode('ASCII'))
type(myasciistring)
<type 'str'>