LoginSignup
1

More than 1 year has passed since last update.

Ruby環境からPythonスクリプトを叩いてデータを得るまで

Posted at

こんにちは。

Rubyを使っているとき、RubyからPythonスクリプトを叩いて、その結果をRubyで表示することが出来たらいいなと考えました。
想定するケース例としては、RailsのバックエンドでPythonの機械学習コードを実行したいといったものになります。

今回のブログでは、Ruby環境からPythonスクリプトを叩いてデータを得るまでについて述べていきたいと思います。

このブログで得ることができる情報は以下になります。

・Ruby環境でPythonスクリプトを実行したいときの手順
・Flaskの簡単な使い方
・RubyのNet::HTTPクラスの簡単な使い方

実装した手順について簡単に概要を。

私が実装した方法は以下になります。

1. Flaskを用いて、PythonスクリプトをAPI化する
2. API化したものをローカル上で実行(Run)する
3. RubyのNet::HTTPクラスを用いてローカル上のAPIを叩く

image.png

私が実装した方法は、とりあえずRubyからPythonスクリプトを叩く流れを理解しておきたい!という方向けです。

ちなみに、今回のフローはこちらのページを参考にしました。

こちらのページでは、APIに認証機能を設ける方法や、HerokuにAPIを挙げる方法も紹介しています。詳細の実装も大変わかりやすく紹介されているので、ぜひご覧になってください。

それでは、早速試してみましょう。

(追記)
PyCallというRubyライブラリを用いることで、Ruby言語内でPythonスクリプトを書けるようです。こちらのライブラリを用いるのが一番近道かもしれないです。
https://github.com/mrkn/pycall.rb/

Flaskを用いて、PythonスクリプトをAPI化する

まずは、PythonスクリプトをAPI化したものを作成してみましょう。

Flaskを用いることで、PythonスクリプトをAPI化することができます。
以下のFlaskの解説動画が非常におすすめです。
Creating a RESTFul API With Flask

Flaskは、Python言語を用いてWebアプリケーションを作成するフレームワークとなっており、DjangoやRailsのようなWebサイトを作成することができます。
Webアプリケーションでは、URLパスとHTTPメソッドが与えられたとき、その組み合わせに応じた画面出力が行われます。例として、Railsのコントローラーが挙がります。
ここで、画面出力の代わりに、JSON形式やXML形式の結果を出力をすることで、APIとして機能することができます。

rest_api_cul.py
from flask import Flask, jsonify, request

app = Flask(__name__)

#cul_inputを書き換えることで、関数をカスタマイズしてください。
def cul_input(input_data: str) -> str:
    return input_data + " yeah!!!"

#APIが無事動いているかどうかのテスト
@app.route("/api/test", methods = ["GET"])
def test():
    return jsonify({"result": "TEST OK"})

#input_dataをcul_inputで計算して、JSONファイルで出力する
@app.route("/api/result/<string:input_data>", methods = ["GET"])
def result(input_data):
    result = cul_input(input_data)
    return jsonify({"result": result})

if __name__ == "__main__":
    app.run(debug=True, port=8080)

詳細部分を解説します。

@app.route("/api/test", methods = ["GET"])
def test():
    return jsonify({"result": "TEST OK"})

@app.route(<path>, methods = [method])
このように記述することで、パスとメソッドの組み合わせを認識させます。この直後に関数を記述することで、リクエストが来た時に関数のリターン部分を出力します。

@app.route("/api/result/<string:input_data>", methods = ["GET"])
def result(input_data):
    result = cul_input(input_data)
    return jsonify({"result": result})

@app.route(<path><type:param>, methods = [method])
このように記述することで、<type:param>部分の変数を関数の引数にすることができます。

if __name__ == "__main__":
    app.run(debug=True, port=8080)

app.run(port=<port>)と記述することで、localhost:<port>/>という形で、ポートが指定されたサーバーが動きます。

以上のスクリプトを記述することで、PythonコードをAPI化することが出来ました。これによって、外部からHTTPリクエストを受け取った時にJSONファイルを返すようになります。

API化したものをローカル上で実行(Run)する

それでは、作成したAPIサーバーをローカルPC上で動かしてみましょう。

ターミナル上でrest_api_cul.pyを実行します。

python3 rest_api_cul.py

以下のようなスクリプトが表示されたら、無事にAPIサーバーが実行(Run)出来ています。
表示されない場合は、スクリプトの誤字脱字や、ポートがすでに使われていることが考えられます。

 * Serving Flask app 'rest_api_cul' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: ooo-ooo-ooo

それでは、curlコマンドでAPIを叩いてみましょう。別のターミナルウインドウを開いて、以下のスクリプトを入力してみます。

JSON出力が得られたら成功です。

#APIが動いているかのテスト
curl -X GET localhost:8080/api/test

#出力
{
  "result": "TEST OK"
}

#引数を"Hello"とするときの入力
curl -X GET localhost:8080/api/result/Hello

#出力
{
  "result": "Hello yeah!!!"
}

RubyのNet::HTTPクラスを用いてローカル上のAPIを叩く

それでは、いよいよRuby環境から、API化したPythonスクリプトを叩いていきましょう。
方針としては、先ほどCurlコマンドでAPIを叩いた手順を、RubyのNet::HTTPクラスによって代用します。
Net::HTTPクラスは、Pythonでいうとrequestモジュールのようなもので、スクリプト内でHTTP通信を用いて外部のサーバーからデータの取得を行うことができます。

作成したRubyスクリプトは以下になります。

result_from_rest_api_cul.rb
require "json"
require "net/http"
require "uri"

word = ARGV[0] #コマンドライン引数を入力

#result/<string:input_data>の部分にwordを代入しURLを作成
url = "http://localhost:8080/api/result/" + word
#URI形式に変換
uri = URI.parse(url)
#GETメソッドでHTTP通信して、APIを叩いてみる
result = Net::HTTP.get(uri)

#APIを叩いた結果を出力
puts result

それでは、ターミナル上で実行してみましょう。以下のような出力結果が得られたら成功です。

#result_from_rest_api_cul.rbを実行する
ruby result_from_rest_api_cul.rb  Hello

#出力結果
{
  "result": "Hello yeah!!!"
}

おわりに

今回実装した、Ruby環境からPythonスクリプトを叩いてデータを得るフローを再掲します。

1. Flaskを用いて、PythonスクリプトをAPI化する
2. API化したものをローカル上で実行(Run)する
3. RubyのNet::HTTPクラスを用いてローカル上のAPIを叩く

このフローを行うことで、RubyとPythonのスクリプト間でデータを送受信できました。
Railsのコントローラーに手順3を盛り込むことで、Rails環境でもPythonスクリプトの使用ができるようになります。

そのため、今度はRailsでのPythonスクリプトの使用方法について、記事で書いていければと考えています。

それでは、最後までお読みいただきありがとうございました!

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
1