**TL,DR;**如何将 Python decimal.Decimal 的实例写入 Protocol Buffer double
字段?
**详细信息;**在 Python 协议缓冲区中,标量消息字段可以是double
。
给定 Python 的decimal.Decimal类的实例:
# Intentionally high-precision number.
d = Decimal(3.14159265358979323846264)
...and 协议缓冲区定义:
message Test {
double value = 1;
}
我想尝试填充Test.value
:
d = Decimal(3.14159265358979323846264)
try:
my_proto_pb2.Test(value=d)
except ValueError:
# Could not store in a `double`.
正如所料,这提高了TypeError
。注意,我except
在ValueError
上因为这是 Python ProtoBuffer type_checkers.py模块引发的。我想要一个ValueError
。我做不要想要TypeError
:)
TypeError:
Decimal('3.14159265358979323846264')
has type <class 'decimal.Decimal'>,
but expected one of: ((<class 'numbers.Real'>,),) for field Test.value
我期望这样,但是,在填充 proto 之前,将Decimal
转换为float
会导致精度损失:
d = Decimal(3.14159265358979323846264)
try:
my_proto_pb2.Test(value=float(d))
except ValueError:
# Could not store in a `double`.
没有TypeError
,但是Test.value
持有3.141592653589793
Protocol Buffers 的 Python 实现使用 TypeChecker 来确定类型和值是否兼容。见google/protobuf/internal/type_checkers.py。但是,只有以下检查器:
-
IntValueChecker
-
EnumValueChecker
-
UnicodeValueChecker
-
Int32ValueChecker
-
Uint32ValueChecker
-
Int64ValueChecker
-
Uint64ValueChecker
因此,以下代码适用于极大的整数,因为Int64ValueChecker
引发ValueError
:
message AnotherTest {
int64 value = 1;
}
...and 对应的 Python:
n = 18446744073709551616
try:
value = my_proto.AnotherTest(value=int(n))
except ValueError:
# Could not store in a `int64`.