ProtocolBuffer出力データとコンパイルされたpythonファイル(.py)の使い方

公開日:
更新日:
目次

Python で Protocol Buffers(protobuf) を扱うことになった人向けの記事です。.proto 定義ファイルから生成された *_pb2.py を使って、メッセージの作成・シリアライズ・ファイル/ネットワーク経由のやり取りまで一通り実装する手順をまとめます。あわせて ImportError などハマりがちなエラーの対処も載せます[1]

Protocol Buffers とは

Protocol Buffers(以下 protobuf)は Google が開発したデータ形式で、JSON や XML より 小さく・速く 構造化データをやり取りできる仕組みです。.proto ファイルにメッセージ定義を書き、専用コンパイラ(protoc)で各言語のコードを生成して使います。Pythonの場合は *_pb2.py というファイルが生成されます。

環境の準備

Python で protobuf を扱うのに必要なものは2つです。

  • ランタイムライブラリ(pip install protobuf
  • .proto ファイルをコンパイルする protocbrew install protobuf 等)
pip install protobuf

protoc のインストールは macOS なら Homebrew、Linux ならパッケージマネージャ、Windows ならGitHub Releases から取得します[1:1]

完全なエンドツーエンド例

理解しやすいよう、.proto 定義からPythonでメッセージを使うまでを通して示します。

.proto ファイルを書く

person.proto を作ります。

syntax = "proto3";

message Person {
  string name = 1;
  int32 age = 2;
  string email = 3;
}

protoc でPythonコードを生成する

protoc --python_out=. person.proto

実行すると person_pb2.py が同じディレクトリに生成されます。

生成された .py をインポートして使う

import person_pb2

# 新しいメッセージインスタンスを作る
person = person_pb2.Person()
person.name = "Alice"
person.age = 30
person.email = "[email protected]"

# シリアライズ(バイト列への変換)
serialized_data = person.SerializeToString()

# 逆シリアライズ(バイト列からの復元)
restored = person_pb2.Person()
restored.ParseFromString(serialized_data)
print(restored.name)  # Alice

*_pb2.py を import するだけで、メッセージ型がPythonクラスとして使えるようになります。

ファイルへの読み書き

シリアライズ済みのバイト列をファイルに保存して、後で復元できます。

# 書き込み
with open('person.bin', 'wb') as f:
    f.write(person.SerializeToString())

# 読み込み
loaded = person_pb2.Person()
with open('person.bin', 'rb') as f:
    loaded.ParseFromString(f.read())

ネットワーク経由での送受信

シリアライズした結果は単なる bytes なので、HTTP・WebSocket・gRPC などお好みの方法で送受信できます。受信側で ParseFromString すれば元のメッセージに戻ります。gRPC を使う場合は protobuf 定義からサーバー/クライアントコードまで一括生成できます。

よくあるエラー

セットアップでつまずきやすい代表的なエラーへの対処です。

ImportError: No module named 'person_pb2'

生成された *_pb2.py がPythonの import パスに無いケース。同じディレクトリに置くか、sys.path に追加します。

import sys
sys.path.append('/path/to/generated')
import person_pb2

TypeError: '...' has type ..., but expected one of: ...

protobuf の型と Python の型が合っていない場合のエラーです。例えば int32 フィールドに文字列を代入すると出ます。.proto の型定義を確認してください。

google.protobuf.message.DecodeError

ParseFromString に渡したバイト列が、対応する protobuf スキーマと一致しないと出ます。よくある原因は次の通りです。

  • 別バージョンの .proto で生成したバイト列を読もうとしている
  • 文字列をバイト列に変換せず渡している(b"..." ではなく "..."
  • ファイルを 'rb' ではなく 'r' で開いている

protoc のバージョン違いによる生成コードの差異

protoc のメジャーバージョンが大きく違うと、生成される *_pb2.py の互換性に問題が出ることがあります。チームで開発する場合は protoc のバージョンを揃えてください。

まとめ

Python で protobuf を使う流れは「pip install protobuf + .proto を書く + protoc*_pb2.py 生成 + import して使う」の4ステップです。エラーの大半は import パス問題型不一致バージョン違い に集約されるので、その3点を切り分けると早く解決できます。

参考文献

脚注
  1. Protocol Buffers Python Tutorial (2026-05-10 アクセス) ↩︎ ↩︎