Как использовать unidecode в python (3.3)

я пытаюсь удалить все символы, отличные от ascii, из текстового документа. Я нашел пакет, который должен сделать именно это,https://pypi.python.org/pypi/Unidecode

он должен принять строку и преобразовать все символы, отличные от ascii, в ближайший символ ascii. Я использовал этот же модуль в perl достаточно легко, просто позвонив while (<input>) { $_ = unidecode($_); } и это один прямой порт модуля perl, документация указывает, что он должен работать тот же.

я уверен, что это что-то простое, я просто не понимаю, достаточно о характере и кодирование файла, чтобы знать, в чем проблема. Мой исходный файл закодирован в UTF-8 (преобразован из UCS-2LE). Проблема может иметь больше общего с моим отсутствием знаний кодирования и обработки строк неправильно, чем модуль, надеюсь, кто-то может объяснить, почему. Я пробовал все, что знаю, без случайной вставки кода и поиска ошибок, которые я получаю без везения, так что далеко.

вот мой питон

from unidecode import unidecode

def toascii():
    origfile = open(r'C:log.convert', 'rb')
    convertfile = open(r'C:log.toascii', 'wb')

    for line in origfile:
        line = unidecode(line)
        convertfile.write(line)

    origfile.close()
    convertfile.close()

toascii();

если я не открою исходный файл в байтовом режиме (origfile = open('file.txt','r') тогда я получаю ошибку UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 1563: character maps to <undefined> С for line in origfile: линии.

если я открою его в режиме байта 'rb' Я TypeError: ord() expected string length 1, but int found С line = unidecode(line) линии.

если я объявляю строку как строку line = unidecode(str(line)) потом он будет писать в файл, но... не совсем так. rn'b'xefxbbxbf[ 2013.10.05 16:18:01 ] User_Name > .xe2x95x90xe2x95x90xe2x95x90xe2x95x90 он выписывает символы n, r и т. д. и unicode вместо их преобразования в что угодно.

если я преобразую строку в строку, как указано выше, и открою convertfile в байтовом режиме 'wb' это дает ошибку TypeError: 'str' does not support the buffer interface

если я открою его в режиме байта, не объявляя его строкой 'wb' и unidecode(line) Я TypeError: ord() expected string length 1, but int found опять ошибка.

1 ответов


на unidecode модуль принимает unicode строковые значения и возвращает строка юникода в Python 3. Вместо этого вы даете ему двоичные данные. Декодируйте в unicode или откройте входной текстовый файл в textmode и Закодируйте результат в ASCII перед записью в файл или откройте выходной текстовый файл в текстовом режиме.

цитирую из документации модуля:

модуль экспортирует одну функцию, которая принимает объект Unicode (Python 2.икс) или строка (Python 3.x) и возвращает строку (это может быть закодировано в байты ASCII в Python 3.x)

выделено мной.

Это должно работать:

def toascii():
    with open(r'C:\log.convert', 'r', encoding='utf8') as origfile, open(r'C:\log.toascii', 'w', encoding='ascii') as convertfile:
        for line in origfile:
            line = unidecode(line)
            convertfile.write(line)

это открывает inputfile в текстовом модусе (используя кодировку UTF8, которая, судя по вашей строке выборки, правильна) и записывает в текстовом модусе (кодировка в ASCII).

вам нужно явно указать кодировку файла, который вы открываете; если вы опустите используется кодировка текущей локали системы (результат locale.getpreferredencoding(False) call), который обычно не будет правильным кодеком, если ваш код должен быть переносимым.