web-dev-qa-db-ja.com

pythonストリームから複数のprotobufメッセージを読み取る例

私は、バイトストリームにシリアル化された複数の異なるprotobufメッセージで構成されるspin3rからのデータを処理しています。

http://code.google.com/p/spinn3r-client/wiki/Protostream

「プロトストリームはプロトコルバッファメッセージのストリームであり、Googleプロトコルバッファの仕様に従って長さのプレフィックスが付いたvarintとしてワイヤ上にエンコードされます。ストリームには、ヘッダー、ペイロード、テールマーカーの3つの部分があります。」

これは、protobufsのかなり標準的なユースケースのようです。実際、protobufコアディストリビューションはC++とJavaの両方にCodedInputStreamを提供します。しかし、protobufはpython-'内部'ツールはこの種の外部使用のためにセットアップされていません:

https://groups.google.com/forum/?fromgroups#!topic/protobuf/xgmUqXVsK-o

だから...私が行って一緒に石畳にする前に、python varintパーサーとさまざまなメッセージタイプのストリームを解析するためのツール:誰かがこれのためのツールを知っていますか?

なぜprotobufから欠落しているのですか? (または私はそれを見つけるのに失敗していますか?)

これは、特に「transport」と「protocol」の両方に対するthriftの同等のツールと比較した場合、protobufにとって大きなギャップのように思われます。私はそれを正しく見ていますか?

16
user1181407

他の回答のコードは ここ から削除される可能性があるようです。このファイルを使用する前にライセンスを確認しましたが、次のようなコードを使用してvarint32sを読み取ることができました。

import sys
import myprotocol_pb2 as proto
import varint # (this is the varint.py file)

data = open("filename.bin", "rb").read() # read file as string
decoder = varint.decodeVarint32          # get a varint32 decoder
                                         # others are available in varint.py

next_pos, pos = 0, 0
while pos < len(data):
    msg = proto.Msg()                    # your message type
    next_pos, pos = decoder(data, pos)
    msg.ParseFromString(data[pos:pos + next_pos])

    # use parsed message

    pos += next_pos
print "done!"

これは、次のメッセージのサイズを表すvarint32sで区切られた単一のタイプのメッセージをロードするように設計された非常に単純なコードです。


更新:以下を使用して、protobufライブラリから直接このファイルを含めることも可能です。

from google.protobuf.internal.decoder import _DecodeVarint32
13
Dragos

small python package を実装して、複数のprotobufメッセージをストリームにシリアル化し、ストリームから逆シリアル化しました。pipでインストールできます。 :

pip install pystream-protobuf

これは、protobufメッセージの2つのリストをファイルに書き込むサンプルコードです。

import stream

with stream.open("test.gam", "wb") as ostream:
    ostream.write(*objects_list)
    ostream.write(*another_objects_list)

次に、ストリームから同じメッセージ(vg_pb2.pyで定義された配置メッセージなど)を読み取ります。

import stream
import vg_pb2

alns_list = []
with stream.open("test.gam", "rb") as istream:
    for data in istream:
        aln = vg_pb2.Alignment()
        aln.ParseFromString(data)
        alns_list.append(aln)
2
cartoonist