ちょっとハマったので備忘録として書き残しておく。
やりたいこと
- 依存関係のある複数のprotoをきちんと変換したい
-
protoc.main()にどういう引数を渡せば良いのか分からない
やったこと
ハンズオンの内容振り返り
protoをpython用へ変換するには、下記の2つの手法がサポートされている。
シェルから直接叩く
$ python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
pythonの中から呼び出す
from grpc.tools import protoc
protoc.main((
'',
'-I.',
'--python_out=.',
'--grpc_python_out=.',
'helloworld.proto',
))
結論から言うと、「ディレクトリを指定して再帰的にprotoを読み込む」のような機能は無く、引数にひとつずつprotoを指定していく必要がある。
そのためシェルでやるのは現実的ではなく、pythonのglob.glob()を使うのが近道だと推測できる。
protoc.main()の引数確認
from grpc.tools import protoc
protoc.main((
'', # おまじない
'-I.', # protoを走査するディレクトリの指定 --proto_path=***でもよい
'--python_out=.', # ***_pb2.pyの保存場所
'--grpc_python_out=.', # ***_pb2_grpc.pyの保存場所 ↑と別々にする利点はほぼ無いと思われる
'helloworld.proto', # 変換するprotoファイルの指定
))
つまり、 protoc.main()にタプルを渡せばよい。
ベタ書きする場合
お尻にどんどん追加するだけでよい。
from grpc.tools import protoc
protoc.main((
'',
'-I.',
'--python_out=.',
'--grpc_python_out=.',
'helloworld.proto',
'hoge.proto',
'fuga.proto',
'poyo.proto',
'piyo.proto'
))
リストを使う場合
前述したように、glob.glob()を用いるとスムーズ。
from grpc.tools import protoc
import glob
protos = glob.glob('hoge/**/*.proto', recursive=True)
protoc.main((
'',
'-I.',
'--python_out=.',
'--grpc_python_out=.',
'helloworld.proto',
*protos
))
*とは何ぞや!?と思った方は「python 可変長引数」でググるとよい。
平たくいうと、リストの頭にアスタリスクを付けることで複数の変数に展開してくれる便利なやつ。