Python 中的 protobuf 中使用了保留关键字
reserved keyword is used in protobuf in Python
一般来说,我有一个使用 Python 关键字 "from" 的 protobuf 定义。它在 Java/C#/C++ 中工作,但是当涉及到 Python 时,我无法为其赋值。
这是我的问题的详细信息。
我有一个如下所示的 protobuf 定义:
message Foo
{
required int64 from = 10
...
}
由于字段"from"是Python中的关键字,在我生成python代码后,我无法编译如下代码:
foo = Foo()
foo.from = 1234
然后,我尝试使用setattr()来设置属性:
setattr(foo, 'from', 1234)
这给了我一个 Protobuf 异常:
AttributeError: Assignment not allowed to composite field "from" in protocol message object.
我现在无法更改定义,因为它已在系统中广泛使用。如果我可以解决使用 Python.
中的 "from" 属性的任何帮助,我们将不胜感激
下面是 ProtoBuf 生成的代码:
import sys
_FOO = _descriptor.Descriptor(
name='Foo',
full_name='com.kerneljoy.Foo',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='from', full_name='com.kerneljoy.Foo.from', index=0,
number=10, type=3, cpp_type=2, label=2,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
extension_ranges=[],
oneofs=[
],
serialized_start=28,
serialized_end=47,
)
DESCRIPTOR.message_types_by_name['Foo'] = _FOO
Foo = _reflection.GeneratedProtocolMessageType('Foo', (_message.Message,), dict(
DESCRIPTOR = _FOO,
__module__ = 'Foo_pb2'
# @@protoc_insertion_point(class_scope:com.kerneljoy.Foo)
))
_sym_db.RegisterMessage(Foo)
经过几次尝试,我发现 setattr() 和 getattr() 可以解决这个问题。因为在我的生产代码中,'from' 指的是另一个 protobuff 定义。所以这里的解决方案如下:
foo = Foo()
object = getattr(foo, 'from')
object.bar = 'value'
object.bar2 = 'value2'
奇怪的是实现了"HasField"却没有配对"GetField"。请考虑另一种实现方式:
def msg_GetField(msg, name, default_value=None, raise_on_not_exist=True):
result = default_value
#
exist = False
items = msg.ListFields()
for desc, value in items:
if name == desc.name:
result = value
exist = True
#
if raise_on_not_exist:
if not exist:
raise ValueError('No property')
#
return result
您可以将其用作实用方法,或者如果您知道该怎么做,可以制作 mixin。
如果 "from" 是原始变量(不是复合变量)。设置属性将起作用(您可以在错误消息中看到: "AttributeError: Assignment not allowed to composite field" )-但是如果 Foo 包含在其他对象中,您将需要使用 "MergeFrom" 插入 Foo 以将其插入包含对象.
示例:
铅:
message Foo
{
required int64 from = 1
}
message Bar
{
required Foo foo = 1
}
以下代码应该有效:
foo=Foo()
bar=Bar()
setattr(foo, 'from', 1204)
bar.MergeFrom(foo)
一般来说,我有一个使用 Python 关键字 "from" 的 protobuf 定义。它在 Java/C#/C++ 中工作,但是当涉及到 Python 时,我无法为其赋值。
这是我的问题的详细信息。
我有一个如下所示的 protobuf 定义:
message Foo
{
required int64 from = 10
...
}
由于字段"from"是Python中的关键字,在我生成python代码后,我无法编译如下代码:
foo = Foo()
foo.from = 1234
然后,我尝试使用setattr()来设置属性:
setattr(foo, 'from', 1234)
这给了我一个 Protobuf 异常:
AttributeError: Assignment not allowed to composite field "from" in protocol message object.
我现在无法更改定义,因为它已在系统中广泛使用。如果我可以解决使用 Python.
中的 "from" 属性的任何帮助,我们将不胜感激下面是 ProtoBuf 生成的代码:
import sys
_FOO = _descriptor.Descriptor(
name='Foo',
full_name='com.kerneljoy.Foo',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='from', full_name='com.kerneljoy.Foo.from', index=0,
number=10, type=3, cpp_type=2, label=2,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
extension_ranges=[],
oneofs=[
],
serialized_start=28,
serialized_end=47,
)
DESCRIPTOR.message_types_by_name['Foo'] = _FOO
Foo = _reflection.GeneratedProtocolMessageType('Foo', (_message.Message,), dict(
DESCRIPTOR = _FOO,
__module__ = 'Foo_pb2'
# @@protoc_insertion_point(class_scope:com.kerneljoy.Foo)
))
_sym_db.RegisterMessage(Foo)
经过几次尝试,我发现 setattr() 和 getattr() 可以解决这个问题。因为在我的生产代码中,'from' 指的是另一个 protobuff 定义。所以这里的解决方案如下:
foo = Foo()
object = getattr(foo, 'from')
object.bar = 'value'
object.bar2 = 'value2'
奇怪的是实现了"HasField"却没有配对"GetField"。请考虑另一种实现方式:
def msg_GetField(msg, name, default_value=None, raise_on_not_exist=True):
result = default_value
#
exist = False
items = msg.ListFields()
for desc, value in items:
if name == desc.name:
result = value
exist = True
#
if raise_on_not_exist:
if not exist:
raise ValueError('No property')
#
return result
您可以将其用作实用方法,或者如果您知道该怎么做,可以制作 mixin。
如果 "from" 是原始变量(不是复合变量)。设置属性将起作用(您可以在错误消息中看到: "AttributeError: Assignment not allowed to composite field" )-但是如果 Foo 包含在其他对象中,您将需要使用 "MergeFrom" 插入 Foo 以将其插入包含对象.
示例:
铅:
message Foo
{
required int64 from = 1
}
message Bar
{
required Foo foo = 1
}
以下代码应该有效:
foo=Foo()
bar=Bar()
setattr(foo, 'from', 1204)
bar.MergeFrom(foo)