pythonに格納した変数を、rubyで受け取る方法をご教授いただきたいです。
以前質問させて頂き『IO.popenを用いることで、pythonのスクリプトを実行して得た結果をrubyの変数に格納して表示する』ことには成功したのですが、python内で変数に格納し、その変数をrubyで叩くことで表示することは難しいのでしょうか?
ご指導ご鞭撻のほどよろしくお願いいたします。。。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
Rails を使っているようなので、
少し大掛かりになりますが、JobQueue システムを構築し
バックエンドでpythonのプログラムを実行という手段もありますね。
通常、他環境との連携には、RPCという方法を用います。
複数言語対応となると思い浮かぶのは、
ProtocolBuffers, Thrift, MessagePack-RPC 辺りでしょうか。
実は、RubyとPythonの標準ライブラリにどちらも xmlrpc があるので
これを用いた、比較的簡単な方法の紹介。
サーバー側(Python)
python
1from xmlrpc.server import SimpleXMLRPCServer 2 3class Service: 4 def __init__(self): 5 self.variables = {} 6 7 def get(self, key): 8 return self.variables.get(key, None) 9 10 def set(self, key, value): 11 self.variables[key] = value 12 return value 13 14 def add(self, lv, rv): 15 return lv + rv 16 17 18def main(host="localhost", port=8001): 19 api = Service() 20 addr = (host, port) 21 server = SimpleXMLRPCServer(addr, allow_none=True) 22 print("Listening on {}:{}".format(*addr)) 23 server.register_multicall_functions() 24 server.register_function(api.get, "get") 25 server.register_function(api.set, "set") 26 server.register_function(api.add, "add") 27 server.serve_forever() 28 29 30if __name__ == '__main__': 31 main()
クライアント側(Ruby)
ruby
1require 'xmlrpc/client' 2 3def main 4 python = XMLRPC::Client.new2("http://localhost:8001/").proxy 5 6 puts python.add(10, 20) 7 puts python.set("a", 100) 8 puts python.get("a") 9end 10 11main if __FILE__ == $0
但し、欠点はあって、
実行してみると解りますが、
HTTP経由の呼び出しなので、オーバーヘッドが大きい。
一桁の数値一個渡すのにも数kb の帯域を使う為、
当然ながら用途や呼び出し頻度によっては効率は良くありません。
前提条件の Rails から使うという事を考えると、
あまり待ち時間が長くなるのは好ましくないでしょう。
この部分の改善にはもう一工夫必要になります。
直接ブラウザに結果を返しても良いのなら、
WebSocket経由で通知する等、他に選択肢もあります。
投稿2020/04/26 08:50
総合スコア8760
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
文字通りには無理なので、両者でデータを共有すると言うことですよね。
いろいろ方法があります。
案1:ファイルで共有する
案2:ファイルで共有するの一種ですが、データベースを使えば自分で方式を設計せずにすみます
案3:OSの共有メモリ機能を使う
案4:それぞれでソケット通信用のスレッドを作り、変数を更新するとき相手に通知して更新してもらう
案5:独立したデータ管理用のプロセスを作り、両者でそれとソケット通信してデータアクセスする
とかでしょうか。
各変数について、更新するのが一方のみと決まっていれば比較的わかりやすいですが、ある変数を両方で更新するとかになると、排他制御の仕組みがいるので、案2が楽でしょうか。
投稿2020/04/26 00:36
総合スコア85901
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
python内で変数に格納し、その変数をrubyで叩くことで表示
そんなご無理を言われても、、、と言うかんじですが。
さすがに実行中のPythonスクリプトの変数をRubyスクリプトに渡すことは無理だと思うので、簡単には、OSの環境変数を介して渡すので要望を満たせませんでしょうか。
環境変数TO_RUBY
(<変数名は何でもよい)に文字列を指定して、子プロセスとしてRubyスクリプトを呼び出してみる例です。親プロセスの環境変数は引き継がれるので、子プロセスであるRubyスクリプトではその値を読み出せます。(ただし、子プロセスでその環境変数を変更しても、親プロセスには影響しません)
呼び出されるRubyのスクリプトは
Ruby
1v = ENV['TO_RUBY'] 2puts("I'm ruby script. TO_RUBY=#{v}")
で、呼び出すPython3のスクリプトは
Python3
1import os 2 3os.environ['TO_RUBY'] = 'Hello, Ruby.' 4os.system('ruby ./t1.rb')
これを実行すると
sh
1$ python3 ./t1.py 2I'm ruby script. TO_RUBY=Hello, Ruby. (from Python) 3$ 4
投稿2020/04/25 17:07
総合スコア9256
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。