**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。注意,我exceptValueError上因为这是 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`.