首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >python -将avro字节逻辑类型decimal反序列化为decimal

python -将avro字节逻辑类型decimal反序列化为decimal
EN

Stack Overflow用户
提问于 2018-09-11 00:56:43
回答 3查看 1.8K关注 0票数 3

我正在尝试使用python Avro库(python 2)读取一个avro文件。当我使用以下代码时:

代码语言:javascript
复制
import avro.schema
from avro.datafile import DataFileReader, DataFileWriter
from avro.io import DatumReader, DatumWriter, BinaryDecoder
reader = DataFileReader(open("filename.avro", "rb"), DatumReader())
schema = reader.meta

然后,它正确地读取每一列,除了保留为字节的列,而不是预期的十进制值。

如何将此列转换为预期的十进制值?我注意到文件的元数据将列标识为'type‘:'bytes',但'logicalType’:'decimal‘

我在下面发布了本专栏的元数据以及字节值(预期的实际值都是1,000小于25,000的倍数。该文件是使用Kafka创建的。

元数据:

代码语言:javascript
复制
 {
                            "name": "amount",
                            "type": {
                                "type": "bytes",
                                "scale": 8,
                                "precision": 20,
                                "connect.version": 1,
                                "connect.parameters": {
                                    "scale": "8",
                                    "connect.decimal.precision": "20"
                                },
                                "connect.name": "org.apache.kafka.connect.data.Decimal",
                                "logicalType": "decimal"
                            }
                        }

字节值:

代码语言:javascript
复制
'E\xd9d\xb8\x00'
'\x00\xe8\xd4\xa5\x10\x00'
'\x01\x17e\x92\xe0\x00'
'\x01\x17e\x92\xe0\x00'

期望值:

代码语言:javascript
复制
3,000.00
10,000.00
12,000.00
5,000.00

我需要在AWS上部署的Lambda函数中使用它,所以不能使用fast_avro或其他使用C而不是纯Python的库。

请参阅以下链接:https://pypi.org/project/fastavro/ https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-python-libraries.html

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-09-11 23:25:37

为此,您需要使用fastavro库。在本文发表时,avroavro-python3库都不支持逻辑类型。

票数 3
EN

Stack Overflow用户

发布于 2021-06-14 12:55:17

您可以使用它将字节字符串解码为十进制。这会将值填充到下一个最高的字节结构中,这样所有可能的值都会适合。

代码语言:javascript
复制
import struct
from decimal import Decimal

def decode_decimal(value, num_places):
    value_size = len(value)
    for fmt in ('>b', '>h', '>l', '>q'):
        fmt_size = struct.calcsize(fmt)
        if fmt_size >= value_size:
            padding = b'\x00' * (fmt_size - value_size)
            int_value = struct.unpack(fmt, padding + value)[0]
            scale = Decimal('1') / (10 ** num_places)
            return Decimal(int_value) * scale
    raise ValueError('Could not unpack value')

例如:

代码语言:javascript
复制
>>> decode_decimal(b'\x00\xe8\xd4\xa5\x10\x00', 8)
Decimal('10000.00000000')
>>> decode_decimal(b'\x01\x17e\x92\xe0\x00', 8)
Decimal('12000.00000000')
>>> decode_decimal(b'\xb2\xb4\xe7\x84', 4)  # Negative value
Decimal('-129676.7100')

参考文献:

https://avro.apache.org/docs/1.10.2/spec.html#Decimal https://docs.python.org/3/library/struct.html#format-characters

票数 1
EN

Stack Overflow用户

发布于 2018-09-11 08:14:17

由于某些原因,fastavro包在同一文件上默认工作。我最终使用了下面的代码。仍然不确定是否有办法直接使用avro库来解决这个问题,或者将上面问题中发布的输出反序列化。

代码语言:javascript
复制
import fastavro
with open("filename.avro", 'rb') as fo: 
    for record in fastavro.reader(fo): 
        print(record) 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52262350

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档