Skip to content

Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

第5章: Python クライアント

サーバが立ったので、クライアントから GetFeature を呼ぶ。

gRPC クライアントは大まかに2つの部品から成る:

  • Channel: サーバへの持続的なコネクション
  • Stub: Channel 上で RPC を呼ぶための代理オブジェクト。proto で定義したメソッド(GetFeature など)が生えていて、ローカルの関数を呼ぶように RPC を叩ける

本章では Channel を作り、そこに RouteGuideStub(第3章で生成)を繋いで、GetFeature を呼ぶ。

ゴール

  • client.py ができている
  • サーバとクライアントを動かして、GetFeature が呼べる

前提

  • 第4章 を完了済み(server.py が動く)
  • サーバを 別ターミナル で起動しておく: python server.py

ステップ 1: client.py を作る

サーバとは 別のターミナル を開き、同じ作業ディレクトリで venv を有効化してから、空の client.py を用意する。

touch client.py

ステップ 2: import を書く

importloggingimportgrpcimportroute_guide_pb2importroute_guide_pb2_grpclogger=logging.getLogger(__name__)

ステップ 3: 1回呼んでみる

まず、Stub を使って GetFeature を1回呼ぶ関数を書く。stub.GetFeature(point) が RPC 呼び出しで、通常の関数呼び出しと同じように書ける。呼ぶとサーバにリクエストが飛び、レスポンスが返るまでブロックする。

defget_one_feature(stub, point):
feature=stub.GetFeature(point)
ifnotfeature.name:
logger.info("No feature at lat=%d lon=%d", point.latitude, point.longitude)
else:
logger.info("Found %r at lat=%d lon=%d", feature.name, point.latitude, point.longitude)
  • stub.GetFeature(point): RPC 呼び出し。同期でブロックし、サーバからのレスポンスが返る。例外が出なければ成功。
  • feature の name が空文字のときは「feature なし」扱い(第4章のサーバ実装と対応)。

ステップ 4: channel と stub を作る

サーバへの接続情報(localhost:50051)を指定して Channel を作り、そこに Stub を繋ぐ。Channel は with ブロックで囲んで、抜けるときに確実に閉じる。

defrun():
withgrpc.insecure_channel("localhost:50051") aschannel:
stub=route_guide_pb2_grpc.RouteGuideStub(channel)
logger.info("-------------- GetFeature --------------")
# feature が見つかる point(サーバの db と一致する座標)point_hit=route_guide_pb2.Point(latitude=407838351, longitude=-746143763)
get_one_feature(stub, point_hit)
# feature が見つからない point(適当な座標)point_miss=route_guide_pb2.Point(latitude=0, longitude=0)
get_one_feature(stub, point_miss)
  • grpc.insecure_channel("localhost:50051"): サーバへのコネクション。with ブロックで確実に閉じる。
  • RouteGuideStub(channel): channel を渡して stub を生成。stub のメソッドが RPC 呼び出しに対応する。

ステップ 5: main を書く

if__name__=="__main__":
logging.basicConfig(level=logging.INFO)
run()

ステップ 6: 動かす

サーバ起動済みのターミナルとは 別のターミナル で:

python client.py

想定される出力:

INFO:__main__:-------------- GetFeature --------------
INFO:__main__:Found 'Patriots Path, Mendham, NJ 07945, USA' at lat=407838351 lon=-746143763
INFO:__main__:No feature at lat=0 lon=0

1行目は feature が見つかった case、2行目は見つからなかった case。

詰まったら answer/client.py を見る。


: 第6章: Go クライアント — 同じ proto から Go のコードを生成し、Python サーバを異言語から叩く。