Заполнение буфера протокола double из Python decimal. Decimal - PullRequest
0 голосов
/ 12 декабря 2018

TL, DR; Как можно записать десятичный экземпляр Python. Десятичный в поле "Буфер протокола" double?

Detail; В буферах протокола Python поле скалярного сообщения *1009* может быть double.

При наличии экземпляра Python десятичный. десятичный класс:

# Intentionally high-precision number.
d = Decimal(3.14159265358979323846264)

... и буфер протокола определение:

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

Я ожидал этого, однако преобразование 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

Реализация протокольных буферов в Python использует TypeChecker, чтобы определить, является ли тип изначения совместимы.См. google / protobuf / internal / type_checkers.py .Однако есть только следующие контролеры:

  • IntValueChecker
  • EnumValueChecker
  • UnicodeValueChecker
  • Int32ValueChecker
  • Uint32ValueChecker
  • Int64ValueChecker
  • Uint64ValueChecker

Следовательно, следующий код работает для очень больших целых чисел , поскольку Int64ValueChecker повышает ValueError:

message AnotherTest {
  int64 value = 1;
}

... и соответствующий Python:

n = 18446744073709551616
try:
  value = my_proto.AnotherTest(value=int(n))
except ValueError:
  # Could not store in a `int64`.
...