こんにちは。
Rubyを使っているとき、RubyからPythonスクリプトを叩いて、その結果をRubyで表示することが出来たらいいなと考えました。
想定するケース例としては、RailsのバックエンドでPythonの機械学習コードを実行したいといったものになります。
今回のブログでは、Ruby環境からPythonスクリプトを叩いてデータを得るまで
について述べていきたいと思います。
このブログで得ることができる情報は以下になります。
・Ruby環境でPythonスクリプトを実行したいときの手順
・Flaskの簡単な使い方
・RubyのNet::HTTPクラスの簡単な使い方
#実装した手順について簡単に概要を。
私が実装した方法は以下になります。
**1. Flaskを用いて、PythonスクリプトをAPI化する
- API化したものをローカル上で実行(Run)する
- RubyのNet::HTTPクラスを用いてローカル上のAPIを叩く**
私が実装した方法は、**とりあえず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として機能することができます。
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スクリプトは以下になります。
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化する
- API化したものをローカル上で実行(Run)する
- RubyのNet::HTTPクラスを用いてローカル上のAPIを叩く**
このフローを行うことで、RubyとPythonのスクリプト間でデータを送受信できました。
Railsのコントローラーに手順3を盛り込むことで、Rails環境でもPythonスクリプトの使用ができるようになります。
そのため、今度はRailsでのPythonスクリプトの使用方法について、記事で書いていければと考えています。
それでは、最後までお読みいただきありがとうございました!