Kesalahan saat membaca file avro dengan python

Saya berhasil menginstal Apache Avro dengan Python. Kemudian saya mencoba membaca file Avro ke Python dengan mengikuti instruksi di bawah ini.

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

Saya memiliki banyak Avros di direktori yang telah ditetapkan sebagai jalur yang benar dengan Python. Ini kode saya:

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()

Namun ia mengembalikan kesalahan ini:

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>

Saya memang sadar bahwa pada contoh di instruksi, skema dibuat terlebih dahulu. Tapi apa itu file avsc? Bagaimana cara membuatnya dan skema yang sesuai dalam kasus saya? Idealnya, saya ingin membaca file Avro ke dalam Python dan menyimpannya ke dalam format csv di disk atau mengetik kerangka data/daftar dengan Python untuk analisis lebih lanjut. Saya menggunakan Python 3 di Windows 7.

DIEDIT Saya mencoba kode Stephane, dan menghasilkan kesalahan baru

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: Kode Stephane berfungsi di sebagian besar kasus, namun terkadang memunculkan AssertionError seperti ini

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 sumber


Jawaban (1)


Anda menggunakan windows dan Python 3.

  • di Python 3 secara default open membuka file dalam mode teks. Artinya ketika operasi pembacaan lebih lanjut terjadi, Python akan mencoba mendekode konten file dari beberapa rangkaian karakter ke unicode.

  • Anda tidak menentukan rangkaian karakter default, jadi Python mencoba memecahkan kode konten seolah-olah konten tersebut dikodekan menggunakan charmap (secara default di windows).

  • jelas file avro Anda tidak dikodekan dalam charmap, dan dekodenya gagal dengan pengecualian

  • sejauh yang saya ingat, header avro adalah konten biner... bukan tekstual (tidak yakin tentang itu). jadi mungkin pertama-tama Anda harus mencoba untuk TIDAK memecahkan kode file dengan open:

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

(perhatikan 'rb', mode biner)

EDIT: Untuk masalah berikutnya (AttributeError), Anda terkena bug umum yang tidak diperbaiki di 1.8.1. Hingga versi berikutnya keluar, Anda dapat melakukan sesuatu seperti:

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()

Sangat aneh bahwa bug bodoh seperti itu bisa dirilis, dan itu bukan pertanda kematangan kode!

person Stephane Martin    schedule 22.11.2016
comment
Saya mencoba kode Anda, tetapi menghasilkan kesalahan baru. Silakan lihat bagian yang diedit dalam pertanyaan. Terima kasih. - person Tracy Yang; 23.11.2016
comment
nah, sepertinya file avro tidak secara eksplisit menentukan codec di header. jika tidak ada codec, spesifikasi mengatakan itu harus 'null'. anehnya implementasinya sepertinya tidak tahu. - person Stephane Martin; 23.11.2016
comment
ini dia: issues.apache.org/jira/browse/AVRO-1741. sepertinya patchnya tidak digabungkan di avro python3 1.8.1. - person Stephane Martin; 23.11.2016
comment
Terima kasih untuk kodenya. Namun tampaknya kode tersebut memiliki beberapa kesalahan. Saya kira di python 3, kita harus menggunakan rb daripada r saat menggunakan open, bukan? Dan di blok kelas, terlihat avro_io dan VALID_CODECS tidak ditentukan. Bagaimana cara memperbaikinya? - person Tracy Yang; 23.11.2016
comment
ya 'rb'. untuk simbol yang tidak terdefinisi, saya menambahkan impor yang diperlukan. - person Stephane Martin; 25.11.2016
comment
Luar biasa, itu berhasil! Tapi bagaimana saya bisa mengubah pembaca menjadi tipe lain? seperti tali. karena saya perlu menguraikan teks lebih lanjut. Terima kasih banyak atas bantuan Anda. - person Tracy Yang; 25.11.2016
comment
Hai, sepertinya ada masalah lain saat membaca file Avro, bisakah Anda melihat pertanyaan yang sudah diedit? - person Tracy Yang; 26.11.2016