Ошибка при чтении файлов avro в python

Я успешно установил Apache Avro в Python. Затем я пытаюсь прочитать файлы Avro в Python, следуя приведенной ниже инструкции.

https://avro.apache.org/docs/1.8.1/gettingstartedpython.html

У меня есть куча Avros в каталоге, который уже задан как правильный путь в Python. Вот мой код:

import avro.schema
from avro.datafile import DataFileReader, DataFileWriter
from avro.io import DatumReader, DatumWriter

reader = DataFileReader(open("part-00000-of-01733.avro", "r"), DatumReader())
for user in reader:
   print (user)
reader.close()

Однако он возвращает эту ошибку:

Traceback (most recent call last):
  File "I:\DJ data\read avro.py", line 5, in <module>
    reader = DataFileReader(open("part-00000-of-01733.avro", "r"), DatumReader())
  File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\datafile.py", line 349, in __init__
    self._read_header()
  File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\datafile.py", line 459, in _read_header
    META_SCHEMA, META_SCHEMA, self.raw_decoder)
  File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 525, in read_data
    return self.read_record(writer_schema, reader_schema, decoder)
  File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg \avro\io.py", line 725, in read_record
    field_val = self.read_data(field.type, readers_field.type, decoder)
  File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 515, in read_data
    return self.read_fixed(writer_schema, reader_schema, decoder)
  File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 568, in read_fixed
    return decoder.read(writer_schema.size)
  File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 170, in read
    input_bytes = self.reader.read(n)
  File "I:\Program Files\lib\encodings\cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 863: character maps to <undefined>

Я действительно в курсе, что в примере в инструкции сначала создается схема. Но что такое файл avsc? Как мне создать его и соответствующую схему в моем случае? В идеале я хотел бы читать файлы Avro в Python и сохранять их в формате csv на диске или в формате dataframe/list в Python для дальнейшего анализа. Я использую Python 3 в Windows 7.

ОТРЕДАКТИРОВАНО Я попробовал код Стефана, и он возвращает новую ошибку

Traceback (most recent call last):
  File "I:\DJ data\read avro.py", line 5, in <module>
    reader = DataFileReader(open("part-00000-of-01733.avro", "rb"), DatumReader())
  File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\datafile.py", line 352, in __init__
    self.codec = self.GetMeta('avro.codec').decode('utf-8')
AttributeError: 'NoneType' object has no attribute 'decode'

EDITED2: код Стефана работает в большинстве случаев, но иногда вызывает ошибку AssertionError, как показано ниже.

Traceback (most recent call last):
File "I:\DJ data\read avro.py", line 42, in <module>
for user in reader:
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\datafile.py", line 522, in __next__
datum = self.datum_reader.read(self.datum_decoder)
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 480, in read
return self.read_data(self.writer_schema, self.reader_schema, decoder)
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 525, in read_data
return self.read_record(writer_schema, reader_schema, decoder)
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 725, in read_record
field_val = self.read_data(field.type, readers_field.type, decoder)
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 523, in read_data
return self.read_union(writer_schema, reader_schema, decoder)
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 689, in read_union
return self.read_data(selected_writer_schema, reader_schema, decoder)
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 493, in read_data
return self.read_data(writer_schema, s, decoder)
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 503, in read_data
return decoder.read_utf8()
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 248, in read_utf8
input_bytes = self.read_bytes()
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 241, in read_bytes
return self.read(nbytes)
File "I:\Program Files\lib\site-packages\avro_python3-1.8.1-py3.5.egg\avro\io.py", line 171, in read
assert (len(input_bytes) == n), input_bytes
AssertionError: b'BlackRock Group\n\n17 December 2015\n\nFORM 8.3\n\nPUBLIC OPENING POSITION DISCLOSURE/DEALING DISCLOSURE BY\n\nA PERSON WITH INTERESTS IN RELEVANT SECURITIES REPRESENTING 1% OR MORE\n\nRule 8.3 of the Takeover Code (the "Code") \n\n\n   1.         KEY INFORMATION \n \n (a) Full name of discloser:                                                                        BlackRock, Inc. \n-------------------------------------------------------------------------------------------------  ----------------- \n (b) Owner or controller of interests and short positions disclosed, if diffe

person Tracy Yang    schedule 22.11.2016    source источник


Ответы (1)


Вы используете окна и Python 3.

  • в Python 3 по умолчанию open открывает файлы в текстовом режиме. Это означает, что когда произойдут дальнейшие операции чтения, Python попытается декодировать содержимое файла из некоторой кодировки в юникод.

  • вы не указали кодировку по умолчанию, поэтому Python пытается декодировать содержимое, как если бы такое содержимое было закодировано с использованием charmap (по умолчанию в Windows).

  • очевидно, что ваш файл avro не закодирован в charmap, и декодирование не выполняется с исключением

  • насколько я помню, заголовки avro в любом случае являются двоичным содержимым... не текстовым (в этом я не уверен). поэтому, возможно, сначала вам следует попробовать НЕ декодировать файл с помощью open:

reader = DataFileReader(open("part-00000-of-01733.avro", 'rb'), DatumReader())

(обратите внимание 'rb', двоичный режим)

РЕДАКТИРОВАТЬ: Что касается следующей проблемы (AttributeError), вы столкнулись с известной ошибкой, которая не исправлена ​​в версии 1.8.1. Пока не выйдет следующая версия, вы можете просто сделать что-то вроде:

import avro.schema
from avro.datafile import DataFileReader, DataFileWriter, VALID_CODECS, SCHEMA_KEY
from avro.io import DatumReader, DatumWriter
from avro import io as avro_io


class MyDataFileReader(DataFileReader):
    def __init__(self, reader, datum_reader):
        """Initializes a new data file reader.

        Args:
          reader: Open file to read from.
          datum_reader: Avro datum reader.
        """
        self._reader = reader
        self._raw_decoder = avro_io.BinaryDecoder(reader)
        self._datum_decoder = None  # Maybe reset at every block.
        self._datum_reader = datum_reader

        # read the header: magic, meta, sync
        self._read_header()

        # ensure codec is valid
        avro_codec_raw = self.GetMeta('avro.codec')
        if avro_codec_raw is None:
            self.codec = "null"
        else:
            self.codec = avro_codec_raw.decode('utf-8')
        if self.codec not in VALID_CODECS:
            raise DataFileException('Unknown codec: %s.' % self.codec)

        self._file_length = self._GetInputFileLength()

        # get ready to read
        self._block_count = 0
        self.datum_reader.writer_schema = (
            schema.Parse(self.GetMeta(SCHEMA_KEY).decode('utf-8')))


reader = MyDataFileReader(open("part-00000-of-01733.avro", "r"), DatumReader())
for user in reader:
    print (user)
reader.close()

Очень странно, что такая дурацкая ошибка могла попасть в релизы, и это не признак зрелости кода!

person Stephane Martin    schedule 22.11.2016
comment
Я попробовал ваш код, но он возвращает новую ошибку. Пожалуйста, смотрите отредактированную часть вопроса. Спасибо. - person Tracy Yang; 23.11.2016
comment
ну, похоже, что файл avro явно не указывает кодек в заголовке. если кодек отсутствует, спецификация говорит, что он должен быть «нулевым». странно реализация, кажется, не знает. - person Stephane Martin; 23.11.2016
comment
вот оно: issues.apache.org/jira/browse/AVRO-1741. патч не слился в avro python3 1.8.1 кажется. - person Stephane Martin; 23.11.2016
comment
Спасибо за код. Но кажется, что код имеет некоторые ошибки. Я предполагаю, что в Python 3 мы должны использовать rb вместо r при использовании open, верно? И в блоке классов он показывает, что avro_io и VALID_CODECS не определены. Как это исправить? - person Tracy Yang; 23.11.2016
comment
да "рб". для неопределенных символов я добавил необходимый импорт. - person Stephane Martin; 25.11.2016
comment
Потрясающе, это работает! Но как я могу преобразовать читатель в другие типы? как струна. так как мне нужно разобрать текст дальше. Большое спасибо за Вашу помощь. - person Tracy Yang; 25.11.2016
comment
Привет, кажется, у него есть другие проблемы при чтении файлов Avro, не могли бы вы взглянуть на отредактированный вопрос? - person Tracy Yang; 26.11.2016