跳转到主要内容

基于Cython的protobuf编译器

项目描述

Pyrobuf库

简介

Pyrobuf是Google Python Protobuf库的替代品。

它生成闪电般的Cython代码,比Google Python Protobuf库快2-4倍,使用它们的C++后端,比Google纯Python实现快20-40倍。

更重要的是,Pyrobuf是自包含的,易于安装。

要求

Pyrobuf需要Cython和Jinja2。如果您想为pyrobuf做出贡献,您可能还需要安装pytest。

Pyrobuf 需要protoc。

Pyrobuf已测试与Python 2.7和Python 3.5兼容。

Pyrobuf似乎在OSX、Linux和Windows上都可以正常工作(对于后者,使Cython正常工作是最复杂的部分,尤其是如果你还在使用2.7的话)。

贡献

人们以许多不同的方式使用protobuf。Pyrobuf处理了AppNexus和其他贡献者的用例,但还不是protoc生成的100%的直接替代品。

你可以帮助使其变得如此!

分叉并克隆仓库,然后运行

$ python setup.py develop

它将生成特定平台的pyrobuf_list,然后编译pyrobuf_listpyrobuf_util模块。

单元测试

您可以直接使用py.test运行测试套件(仍在进行中)

$ py.test

或使用test命令(如果尚未安装pytest,则会安装pytest)

$ python setup.py test

任何一种方法都会自动构建tests/proto中的所有protobuf消息规范,并在运行测试之前将PYTHONPATH指向构建的消息。

重新运行developtest命令将自动重新构建pyrobuf_listpyrobuf_util模块(如果需要的话)。

clean命令会为您做清洁工作

$ python setup.py clean

如果您发现pyrobuf对您的某个proto文件不起作用,请在提交pull请求之前,向tests/proto添加一个最小的proto文件,该文件在提交之前会破坏。

包括破坏性测试的pull请求是宝贵的!

改进测试正在进行中。

安装

您很可能可以直接使用pyrobuf……只需pip它!

$ pip install pyrobuf

应该可以了!

为了检查,您可能想确保以下命令不会引发异常

$ python -c "import pyrobuf_list"

如果它引发了异常,请尝试

$ pip install pyrobuf -v -v -v --upgrade --force --no-cache

编译

当您pip install pyrobuf时,您会得到pyrobuf CLI工具……

$ pyrobuf --help
usage: pyrobuf [-h] [--out-dir OUT_DIR] [--build-dir BUILD_DIR] [--install] source

a Cython based protobuf compiler

positional arguments:
  source                filename.proto or directory containing proto files

optional arguments:
  -h, --help            show this help message and exit
  --out-dir OUT_DIR     cythonize output directory [default: out]
  --build-dir BUILD_DIR
                        C compiler build directory [default: build]
  --install             install the extension [default: False]
  --package             the name of the package to install to

如果您不想处理setuptools entry_points的特殊性,您也可以这样做

$ python -m pyrobuf --help

使用

假设您已安装了包含消息Test规范的test_message.proto。在Python中,您可以通过运行以下代码来导入您的新消息类

from test_message_proto import Test

导入消息类后,我们可以创建一个新消息

test = Test()

现在我们已经实例化了消息test,我们可以填充单个字段

>>> test.field = 5
>>> test.req_field = 2
>>> test.string_field = "hello!"
>>> test.list_fieldx.append(12)
>>> test.test_ref.field2 = 3.14

并且可以访问这些相同的字段

>>> test.string_field
'hello!'

一旦我们至少填写了所有“必需”字段,我们就可以将它们序列化为字节数组

bytearray(b'\x10\x05\x1a\x06hello! \x0c2\t\x19\x1f\x85\xebQ\xb8\x1e\t@P\x02')

我们还可以将protobuf消息反序列化到我们的消息实例中

>>> test.ParseFromString('\x10\x05\x1a\x06hello! \x0c2\t\x19\x1f\x85\xebQ\xb8\x1e\t@P\x02')
25

请注意,ParseFromString方法返回消耗的字节数。

除了将protobuf消息序列化和反序列化到和从以及JSON和原生Python字典之外,Pyrobuf还允许我们进行整数编码和解码。

>>> test.SerializeToJson()
'{"field": 5, "req_field": 2, "list_fieldx": [12], "string_field": "hello!", "test_ref": {"field2": 3.14}}'

>>> test.ParseFromJson('{"field": 5, "req_field": 2, "list_fieldx": [12], "string_field": "hello!", "test_ref": {"field2": 3.14}}')

>>> test.SerializeToDict()
{'field': 5,
 'list_fieldx': [12],
 'req_field': 2,
 'string_field': 'hello!',
 'test_ref': {'field2': 3.14}}

pyrobuf_util模块包含整数编码和解码的函数。

>>> import pyrobuf_util
>>> pyrobuf_util.to_varint(2**16-1)
bytearray(b'\xff\xff\x03')
>>> pyrobuf_util.from_varint(b'\xff\xff\x03', offset=0)
(65535L, 3)
>>> pyrobuf_util.to_signed_varint(-2**16)
bytearray(b'\xff\xff\x07')
>>> pyrobuf_util.from_signed_varint(b'\xff\xff\x07', offset=0)
(-65536L, 3)

from_varintfrom_signed_varint函数返回解码的整数和源数据中编码整数后的第一个字节的偏移量。

打包

如果您正在编译多个消息或消息目录,并且不希望它们都构建为单独的包,而是希望包含所有消息的单个命名空间,您可以指定一个包名

pyrobuf /path/to/proto/specs --install --package=my_messages

然后您可以从my_messages包导入您的消息类

>>> from my_messages import MyMessage1, MyMessage2

使用Pyrobuf模块分发Python包

假设您有一个名为'sample'的Python包,其磁盘上的组织方式如下

sample/
    proto/
        my_message.proto
    sample/
        __init__.py
    setup.py

Pyrobuf添加了一个新的setup关键字pyrobuf_modules,可以用来指定单个protobuf文件或包含protobuf文件的目录。例如,setup.py文件可能看起来像这样

from setuptools import setup, find_packages

setup(
    name="sample",
    version="0.1",
    packages=find_packages(),
    description="A sample package",
    install_requires=['pyrobuf'],
    setup_requires=['pyrobuf'],
    pyrobuf_modules="proto"
)

除了“sample”包之外,setuptools还会构建一个名为“sample_proto”的包,其中包含编译后的Protobuf消息。

安装此示例包后,可以使用以下方式使用它

>>> from sample_proto import MyMessage
>>> my_message = MyMessage()

性能

在我的开发机器(Ubuntu 14.04)上,当使用Google库的C++后端时,Pyrobuf在消息序列化方面的速度大约是Google库的2.0倍,在消息反序列化方面的速度是Google库的2.3倍。

> python tests/perf_test.py
Google took 1.649168 seconds to serialize
Pyrobuf took 0.825525 seconds to serialize
Google took 1.113041 seconds to deserialize
Pyrobuf took 0.466113 seconds to deserialize

如果不使用C++后端,Pyrobuf在序列化方面的速度大约是Google库的25倍,在反序列化方面的速度是Google库的55倍。

Google took 20.215662 seconds to serialize
Pyrobuf took 0.819555 seconds to serialize
Google took 24.990137 seconds to deserialize
Pyrobuf took 0.455732 seconds to deserialize

与Google库的差异

如果Pyrobuf缺少您从protoc中需要的功能,请告诉我们!我们正尽力让您更容易帮助我们使Pyrobuf变得更好。

总的来说,Pyrobuf应该是Google protobuf库的直接替代品。尽管如此,还有一些差异。首先,Pyrobuf目前没有实现ListFieldsWhichOneOfHasExtensionClearExtensionByteSize方法。

其次,Pyrobuf简单假设用于特定消息的模式在发送和接收端是相同的,因此在一个端点上更改字段的类型而不在另一端更改可能会导致错误;添加或删除字段不会破坏任何东西。

项目详情


下载文件

下载适用于您平台的项目文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源代码分发

pyrobuf-0.9.3.tar.gz (258.5 kB 查看哈希值)

上传时间 源代码

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面