LINUX.ORG.RU

Ошибка чтения plain-text скриптом на Python 3

 


0

1

Python 3. Имеется скрипт, который определяет кодировку файла, перекодирует в UTF-8 (при необходимости) и загружает текст. При попытке чтения некоторых файлов получаю ошибку:

  File "/usr/local/bin/main.py", line 310, in load_array
    array=f.read().splitlines()
  File "/usr/lib/python3.1/codecs.py", line 300, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xd0 in position 0: invalid continuation byte
Пробовал и так и эдак, пересохранял файл в разных кодировках в LibreOffice и Word - безрезультатно. charade (форк от chardet) показывает, что кодировка utf-8. Здесь прочитал, что

utf-8 хранит русские буквы в хитром формате, где первый байт 0xd0.

Так может быть, этот байт как-то специально вставлять надо? Если так, то как это делается и как определяется, вставлен ли этот байт?

Deleted

utf-8 хранит русские буквы в хитром формате, где первый байт 0xd0.

не стоит читать всякий шлак и заниматья гаданием. Начать стоит с приведения небольшого куска байтовой строчки (первые 6-8 байт, фейлится на втором байте) на которой наблюдается проблема. Вероятно даёшь невалидный utf8

mashina ★★★★★
()
Ответ на: комментарий от mashina

Текст начинается так:
«1. Предложено $производное соединения»
Пробовал убирать «1. », вставлял текст до этого - безрезультатно. Весь текст привести не могу - он по работе.

Deleted
()
Ответ на: комментарий от mashina

А как проверить его валидность?

Deleted
()
Ответ на: комментарий от mashina
00000000  31 2e 20 d0 9f d1 80 d0  b5 d0 b4 d0 bb d0 be d0  |1. .............|
00000010  b6 d0 b5 d0 bd d0 be 20  24 d0 bf d1 80 d0 be d0  |....... $.......|
00000020  b8 d0 b7 d0 b2 d0 be d0  b4 d0 bd d0 be d0 b5 20  |............... |
Deleted
()
Ответ на: комментарий от Deleted

Короче, попробуй обновить питон. Там никаких апдейтов для дистра нет? Вообще, 3.1 это старьё жуткое...

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

utf-8 — не умолчальное. В третьепитоне open() без указания encoding платформо- и локалезависим.

x3al ★★★★★
()
Ответ на: комментарий от Deleted
def detect_encoding(path):
        """Return a string describing the probable encoding of a file."""
        u = UniversalDetector()
        for line in open(path, 'rb'):
                u.feed(line)
        u.close()
        result = u.result
        if result['encoding']:
                return '[%s]: %s с вероятностью %s' % (path,result['encoding'],result['confidence'])
        else:
                return 'unknown'

# Изменить кодировку текстового файла
def convert_file(file_w,source_encoding,target_encoding):
        try:
                a = codecs.open(file_w,"r",source_encoding).read()
                codecs.open(file_w,"w",target_encoding).write(a)
                print('Кодировка файла %s успешно изменена.' % file_w)
        except:
                Warning('Не удается изменить кодировку файла %s!' % file_w)

# Изменить кодировку файла на принятую по умолчанию (если требуется)
def reencode(file):
        source_encoding=detect_encoding(file)
        source_encoding=re.sub(".*]: ",'',source_encoding)
        source_encoding=re.sub(" с вероятностью .*",'',source_encoding)
        if source_encoding==default_encoding:
                print("[%s]: перекодировка не требуется" % file)
        else:
                convert_file(file,source_encoding,default_encoding)
                print("[%s]: перекодирован в %s" % (file,default_encoding))
Deleted
()
Ответ на: комментарий от Deleted

Конкретно здесь — нет. open без аргументов открывает файл как текстовый. У каждого текстового файла есть кодировка. Если не указываешь её явно, то python вынужден использовать локаль.

x3al ★★★★★
()
Ответ на: комментарий от x3al

Предполагается, что в винде кодировка будет cp1251, в линуксе - utf-8 - в зависимости от того, где был создан файл.

Deleted
()

В общем, все оказалось до банальности просто :( Еще раз почитав вывод с ошибкой (я привел только конец), я увидел, что читается на самом деле не основной текстовый файл, а второстепенный (скрипт большой, выполняет много операций), имя которого определяется по заданному шаблону. Ну так вот, где-то здесь закралась ошибка, и вместо того, чтобы читать 'amended claims - ru (2011-11-11)', он пытается прочитать 'amended claims - ru (2011-11-11) (marked).doc' и вываливается с ошибкой. Как же все просто :(

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.