10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

gRPCでElixirとPython間通信をする

10
Last updated at Posted at 2020-05-18

1.はじめに

Elixir~Python間を、gRPCを使って異言語間通信を試してみます。

今回の記事では、

  • gRPCサーバ:Elixir
  • gRPCクライアント:Python3

としています。

実行環境

ハード Raspberry Pi 3B+
OS Raspbian Buster, Ubuntu Server 20.04LTS
Python 3.7.3
Elixir 1.7.4 (compiled with Erlang/OTP 21)
※いづれもaptパッケージでインストールできるもの

2.Elixir側

最初に、Elixir側の準備をします。

ここでは、elixir-grpcのライブラリに含まれているサンプル「examples/helloworld」を使ってみます。

クライアントからnameに名前を代入してリクエストすると、サーバからは"Hello "という文字列が帰ってきます。

※詳しい手順は別記事にまとめてますので、こちらをご覧下さい。

コマンドライン
$ pwd
..../elixir/
# クローンします
$ git clone https://github.com/elixir-grpc/grpc.git
# サンプルディレクトリに移動して
$ cd ./grpc/examples/helloworld/
# 依存関係の処理、コンパイルします。
$ mix do deps.get, compile

2.Python側

次はPython側でクライアント・サーバを作る手順を示します。

(1)grpcツールのインストール

コマンドライン
$ pip3 install grpcio grpcio-tools protobuf

(2)インターフェースの生成

protoファイルを解析して、Python向けのインターフェースを生成するツールを準備します。

コマンドライン
$ pwd
..../elixir/grpc/examples/helloworld
# Pythonのスクリプトを保存するフォルダを作成
$ mkdir python
$ cd python
# elixirのほうで定義している、protoファイルをコピー
python $ cp ../priv/protos/helloworld.proto ./
# ツールのファイルを生成
python $ touch codegen.py
python $ chmod 755 codegen.py

Python向けのインターフェースを生成するツールのソースコードです。
今回はhelloworld.protoを対象にしてるので、コード中では__NAME="helloworld"としています。

codegen.py
# !/usr/bin/env /usr/bin/python3
# -*- coding: utf-8 -*-
"""
protoファイルのコンパイル

以下の2つのファイルが生成されます。
・*_pb2.py      : シリアライズのインターフェース
・*_pb2_grpc.py : gRPCのインターフェース
"""
from grpc.tools import protoc

# protoのファイル名(の名前部分)
__NAME="helloworld"

# Python向けのインターフェースを生成
protoc.main(
    (
        '',
        '-I.',
        '--python_out=.',
        '--grpc_python_out=.',
        ('{}.proto'.format(__NAME)),
    )
)

Python向けのインターフェースを生成します。

コマンドライン
python $ ./codegen.py
python $ ls
codegen.py  helloworld_pb2_grpc.py  helloworld_pb2.py  helloworld.proto

*_pb2.pyと、*_pb2_grpc.pyの二つのファイルが生成されました。

(3)Python側クライアントの作成

クライアントのスクリプトを作成

コマンドライン
# ファイルを生成
python $ touch client.py
python $ chmod 755 client.py
client.py
# !/usr/bin/env /usr/bin/python3
# -*- coding: utf-8 -*-
"""
gRPCクライアント
by myasu 2020 
"""

import sys
import grpc
# 先ほどprotoから生成したインターフェースをインポート
import helloworld_pb2
import helloworld_pb2_grpc


def grpc_client(request):
    """gRPCクライアントの通信処理
    Parameters
    ----------
    request : string
        gRPCサーバに送るメッセージ
    """
    # Elixir側のgRPCサーバのアドレスとポートを指定して接続
    with grpc.insecure_channel('localhost:50051') as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        # Elixir側のgRPCサーバにrequestする
        response = stub.SayHello(helloworld_pb2.HelloRequest(name=request))

    # responseの内容を確認
    print(' Response:', response.message)


if __name__ == '__main__':
    """メイン処理
    """
    # 引数の読み込み
    args = sys.argv
    # 引数の長さをチェック
    if len(args) == 2:
        # 実行
        grpc_client(args[1])
    else:
        # エラー
        print('Arguments are too short')

Python→Elixir→Python間の通信テスト

最初にサーバ・Elixir側を起動します。

ターミナル1・ElixirのgRPCサーバ側
$ mix grpc.server
10:58:01.872 [warn]  cowlib should be >= 2.9.0, it's 2.8.1 now. See grpc's README for details
10:58:01.977 [info]  Running Helloworld.Endpoint with Cowboy using http://0.0.0.0:50051

(・・・ここから先はクライアントの要求があったときに表示・・・)
22:58:04.739 [info]  Handled by Helloworld.Greeter.Server.say_hello
22:58:04.744 [info]  Response :ok in 4ms
22:58:09.237 [info]  Handled by Helloworld.Greeter.Server.say_hello
22:58:09.237 [info]  Response :ok in 15μs
22:58:13.552 [info]  Handled by Helloworld.Greeter.Server.say_hello
22:58:13.552 [info]  Response :ok in 15μs
[Ctrl-\]で停止

次にクライアント・Python側を実行します。
スクリプトの引数には、任意のメッセージが指定できます。

ターミナル2・PythonのgRPCクライアント側
python $ ./client.py chika
 Response: Hello chika
python $ ./client.py you
 Response: Hello you
python $ ./client.py ruby
 Response: Hello ruby
python $ ./client.py CYaRon!
 Response: Hello CYaRon!

メッセージの先頭に、サーバ側が"Hello "を付けて返してきます。
このような感じで、異種言語間の通信が出来ました。

4.その他

(1)grpc-toolsのインストール方法

20年6月現在、RaspbianUbuntu 20.04LTSのaptでpython3-grpcio python3-grpcio-toolsでインストールすると、下記バージョンが入ります。

python3-grpc-tools 1.14.1-1build3 Protobuf code generator for gRPC (Python 3)
python3-grpcio 1.16.1-1ubuntu5 GRPC system (Python 3)

1.23.0よりも前のバージョンでは、wait_for_termination命令がサポートされていませんので、実行時に下記のエラーメッセージが出ます。

エラーメッセージ
AttributeError: '_Server' object has no attribute 'wait_for_termination'

従って、現時点ではaptではなく、pip3でインストールして下さい。

参考: https://github.com/grpc/grpc/issues/20333

5.参考資料

10
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?