Python读取Avro文件仅在Windows环境报错问题咨询
我之前也碰到过一模一样的问题!你的代码在OSX/Linux正常但Windows报错,核心原因是旧版本avro库对Python 3的二进制文件处理逻辑有兼容bug,咱们一步步拆解:
先复盘你的场景
你的代码本身逻辑没问题:
from avro.datafile import DataFileReader, DataFileWriter from avro.io import DatumReader, DatumWriter reader = DataFileReader(open("my_file.avro", "rb"), DatumReader()) for line in reader: print(line) break
但在Windows上会抛出类似这样的完整报错(补全常见的完整报错信息):
Traceback (most recent call last):
File "", line 2, in
File "C:\Program Files\Python36\lib\site-packages\avro\datafile.py", line 353, in next
datum = self.reader.read(self.datum_reader)
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 584, in read
return self.datum_reader.read(self.decoder)
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 220, in read
return self.read_data(self.writer_schema, self.reader_schema, decoder)
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 274, in read_data
return self.read_record(writer_schema, reader_schema, decoder)
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 483, in read_record
field_val = self.read_data(field.type, reader_field.type, decoder)
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 253, in read_data
return self.read_union(writer_schema, reader_schema, decoder)
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 318, in read_union
return self.read_data(union_schema[selected], reader_schema, decoder)
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 274, in read_data
return self.read_record(writer_schema, reader_schema, decoder)
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 483, in read_record
field_val = self.read_data(field.type, reader_field.type, decoder)
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 265, in read_data
return decoder.read_bytes()
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 134, in read_bytes
length = self.read_long()
File "C:\Program Files\Python36\lib\site-packages\avro\io.py", line 112, in read_long
b = ord(self.read(1))
TypeError: ord() expected string of length 1, but int found
为什么只有Windows报错?
其实不是系统的锅,是Python 3的二进制文件读取特性+旧avro库的适配缺陷共同导致的:
- 在Python 3中,用
"rb"模式打开文件时,read(1)返回的是长度为1的bytes对象,而不是字符串。 - 旧版avro库的
io.py里,错误地用ord()处理这个结果——ord()原本是用来把单个字符(str类型)转成ASCII码,但bytes对象的元素本身就是int类型,直接用ord()就会触发类型错误。 - 你在Linux/OSX上能运行,大概率是因为这两个系统上安装的avro库版本已经修复了这个bug,或者你无意中用了适配Python3的分支版本。
解决办法(按优先级排序)
1. 升级到兼容Python3的avro库
这是最稳妥的方案,卸载旧版avro,安装官方适配Python3的版本:
# 先卸载旧库 pip uninstall avro # 安装专门适配Python3的分支,或者官方最新版 pip install avro-python3 # 或者安装apache官方维护的最新avro库(推荐) pip install apache-avro
升级后再运行你的代码,应该就能正常读取Avro文件了。
2. 临时修复旧版库的代码(应急用)
如果暂时无法升级库,可以手动修改报错里指向的avro/io.py文件:
找到read_long方法里的这行代码:
b = ord(self.read(1))
把它改成:
b = self.read(1)[0]
因为self.read(1)返回的是bytes对象,取第一个元素就是对应的int值,完全不需要用ord()转换。
3. 优化文件路径(可选)
另外,Windows下的文件路径如果包含转义字符(比如\),建议用原始字符串或者双反斜杠,避免路径解析错误:
# 用原始字符串 reader = DataFileReader(open(r"C:\your\path\my_file.avro", "rb"), DatumReader()) # 或者双反斜杠 reader = DataFileReader(open("C:\\your\\path\\my_file.avro", "rb"), DatumReader())
这不是导致报错的直接原因,但能避免后续可能出现的路径问题。
内容的提问来源于stack exchange,提问作者mgoldwasser

