質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

Rails5からPythonスクリプトを実行したい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,625
退会済みユーザー

退会済みユーザー

実現したいこと

Railsアプリケーションのユーザ側から、3つのファイル提供を受け、inputとして受け取る。(ファイルはDBに保存せずに、使い捨て?のような形をとりたい。)
そして、link_toメソッドで「実行」をクリックすると、Pythonスクリプトが実行され、outputがViewに出力されるようにしたい。
※link_toメソッドでなくても、ページ遷移に伴ってpythonスクリプトを実行したい。

イメージ画像
イメージ説明

しかし

・アプリケーション内のどのディレクトリにPythonスクリプトファイルを置くべきかわからない。
・どこからPythonスクリプトを呼び出せば良いか確信が持てない。link_toメソッドで飛ばしたコントローラのアクション内か?
・受け取るファイルを、Pythonスクリプト内に反映させるにはどうしたら良いのか?

参考にした情報と学んだ内容(1時間程度調べてみました。番号は学習した段階を表しています。)

1,teratailから得られた情報
→そもそも、RailsからPythonスクリプトを実行できるかどうかすらわからなかったが、この記事を閲覧することで、呼び出し自体は難なく行うことができることを確認。
2,Rubyで外部コマンドを実行して結果を受け取る方法あれこれ
→Qiitaの記事。どんぴしゃりの内容だと感じ、閲覧したものの、情報の価値がわからないという体たらく。しかし、ここから得られることは多そうだと感じた。
3,railsのwebシステム内にpythonのスクリプトを共存させることは可能でしょうか?
→これまたどんぴしゃりの内容だ!!と感じて閲覧したものの、読んでも書いてあることがわからないので、それぞれの言葉を確認しながら調べている最中。
とりあえず、この回答を信頼して、外部スクリプトの実行を体験したことがない自分は、IO.popenを使用するのが現段階では難易度的にベストと感じ、調べている最中です。

質問内容

IO.popen公式ドキュメント?
→何が書いてあるのか全くわからん。という状態です。外部スクリプトの実行に関する内容があると想定していたのですが・・・
このサイトを理解するために何をするべきでしょうか?というのが今回の質問です。お答えいただけると幸いです。

ベストアンサーの選択について

ご回答いただいた3人の識者の方のおかげで、自分が実現したいことに対して、大まかな方針を立てることが可能になりました。
まず、3人の識者の方にお礼申し上げます。ありがとうございました。
さて、本題についてですが、「質問内容」に対してもっとも的確にお答えいただいた方を選択することにしました。
今後ともよろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

Pythonプログラムの出力をプログラムで扱わないのであれば、systemでもいいのですが、標準出力を変数に取得したいということであれば、バッククォートによる実行が必要です。

system("python -V") # バージョン文字列を標準出力に出す

python_version = `python -V` # バージョン文字列を変数に取得

また、Pythonプログラムの標準入力になにかを渡したいとか、標準出力を順次読み取りたいとかであれば、参考にされたページにある、IO.popenとかopen3モジュールとかを使う必要があります。

→何が書いてあるのか全くわからん。という状態です。外部スクリプトの実行に関する内容があると想定していたのですが・・・

外部スクリプトというか、外部コマンドの実行ですね。サンプルとして、標準入力を標準出力に出すコマンドcatコマンドの実行例と、ファイル一覧を出すlsコマンドの実行例が載っていますが、これをpythonに変えるだけです。

このサイトを理解するために何をするべきでしょうか?というのが今回の質問です。お答えいただけると幸いです。

少なくとも、popenを理解するには、ファイルディスクリプタ(標準入力、標準出力、標準エラー出力、その他一般のファイルディスクリプタ)、(ファイルディスクリプタの)リダイレクト、パイプ、プロセスなどについての知識がある程度ないと難しいと思います。
Linux入門のやや難しめの物を読むと良いのではないでしょうか。適度な本があるかどうか知りませんが。

「Unixプログラミング」「Linuxプログラミング」と言ったシステムコールを使うプログラミングの本を読めば十分ではあるのですが、「RubyからPythonを起動したい」レベルの話にはそこまで必要ではないと思うので、この手の本を読むのは手間をかけすぎという気がします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/28 23:18

    Pythonプログラムには、ユーザ側から3つのファイルの入力を求める予定です。それをPythonプログラムに渡しプログラムを実行させます。
    出力は単にViewで表示できれば良いという状況です。(現状では、ですが・・)
    つまり、systemでも大丈夫という認識で大丈夫でしょうか?

    >Pythonプログラムの標準入力になにかを渡したい
    あ、ダメそうですね。調べた内容通り、popenを理解しないといけない流れになる気がします。

    >少なくとも、popenを理解するには、ファイルディスクリプタ(標準入力、標準出力、標準エラー出力、その他一般のファイルディスクリプタ)、(ファイルディスクリプタの)リダイレクト、パイプ、プロセスなどについての知識がある程度ないと難しいと思います。
    「ファイルディスクリプタ」という言葉そのものを聞いたことなかったです。勉強しないといかんということですね。

    >「Unixプログラミング」「Linuxプログラミング」と言ったシステムコールを使うプログラミングの本を読めば十分ではあるのですが、「RubyからPythonを起動したい」レベルの話にはそこまで必要ではないと思うので、この手の本を読むのは手間をかけすぎという気がします。
    少し、これらの本について調べてみたいと思います。

    キャンセル

  • 2019/10/28 23:41

    「cat というプログラムに、その標準入力からデータを与え、その標準出力からデータを得る」
    という短いサンプルが公式リファレンスのIO.popenに載っているので参考になるかと思います。

    > 「ファイルディスクリプタ」という言葉そのものを聞いたことなかったです。勉強しないといかんということですね。

    サンプルをもとにpopenを使うだけであれば、「標準入力、標準出力、標準エラー出力」が理解できていれば十分かと思います。あと、リダイレクトの概念と。
    systemは実行だけするもの。IO.popenやopen3ライブラリは実行と入出力のリダイレクトを行います。

    > 少し、これらの本について調べてみたいと思います。
    いや、回答に書いた通り、「手間かけすぎ」だと思いますよ。

    とにかく、「単純なPythonプログラム」を利用するコードをIO.popenで書いてみましょう。

    キャンセル

  • 2019/10/30 11:09

    ご回答ありがとうございます。
    返信が遅れまして、申し訳ないです。

    >とにかく、「単純なPythonプログラム」を利用するコードをIO.popenで書いてみましょう
    これをまずやってみて、できたら先に進もうと思います。ありがとうございました。

    キャンセル

+1

RailsからPythonを実行しようと思ったことがないのですが、パッと思いつくのは
Kernel.#systemでシェル経由でPythonスクリプトを実行することですかね。

IOクラスはファイルを読み込んだり書き込んだりしたりするときに使うものなので

RailsからPythonスクリプトを実行

には適していないかなと思います。

さて、質問への回答ですが

このサイトを理解するために何をするべきでしょうか?

Rubyをある程度理解している前提であれば、実際にサンプルコードを書いて色々試してみるのが一番だと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/28 17:29 編集

    イメージ違いでしたか、お恥ずかしいです。おそらく修正するべきですね。

    丁寧にリンクまでいただいて、ありがとうございます。確認いたしました。
    ファイルのpathをrequestで探すのですね。
    https://keruuweb.com/ruby-tempfile%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9/
    綺麗に描かれているサイトでも確認してみました。
    疑問が湧いてきたのですが、この処理(一番下のpathの説明)は、アプリケーションのどこで行うのでしょうか?画面遷移に伴わせてPythonスクリプトを動かしたい場合は、コントローラでこの処理を書けば良いでしょうか?

    キャンセル

  • 2019/10/28 17:36

    > アプリケーションのどこで行うのでしょうか?

    フォームの値を受け取って画面をレンダリングするまでの間で行います。
    コントローラで行うのが一番手っ取り早いですが、
    場合によってはモデルに書いたりモジュールに切り出したりもします。
    どこに書こうがそのコードが実行されれば動きます。
    好みというかアプリケーション次第というかこの辺りはFatControllerとかで調べればいいです。
    コントローラに処理を書きすぎてしまう問題です。特に問題なければコントローラでもいいと思います。

    キャンセル

  • 2019/10/28 22:55

    返信が遅くなりすみません。少し体調悪いので、実際に検証するのは明日になりそうです。
    内容についてなるほどです。
    今回はそこまでコード量が多くないので、コントローラーに記載しようと思います。
    あとは、実際に作業します。

    キャンセル

+1

前提:Pythonをインストールしてパスを通しておくこと。

  1. ファイルを任意の場所に配置する。
  2. 配置した場所を "sample.py" のところに記述する。
  3. 標準出力は stdout, 標準エラー出力は stderr に格納されるのでそれを View に表示する。
require 'open3'

stdin, stdout, stderr, wait_thr = *Open3.popen3("python sample.py")

puts stdout.read # => 標準出力
puts stderr.read # => 標準エラー出力


参考:
パス (path)とは
「PATH を通す」の意味をできるだけわかりやすく説明する試み
Rubyから外部プログラムを起動する方法まとめ
Open3.#popen3

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/28 23:25

    簡潔なご回答ありがとうございます!
    1,Pythonプログラムにユーザーからファイルの提出を求めているのですが、その場合の処理についてはどのようにするべきでしょうか?
    2,ページの遷移に従ってプログラムを実行したいので、コントローラで実行することを念頭においているのですが、そうなると、
    >stdin, stdout, stderr, wait_thr = *Open3.popen3("python sample.py")
    この部分で代入している部分をインスタンス変数として扱わないとViewに渡せないと思います。これは以下のようにすれば良いのでしょうか?
    コントローラ
    @stdin, stdout, stderr, wait_thr = *Open3.popen3("python sample.py")
    View
    @stdout.read => 標準出力
    @stderr.read => 標準エラー出力

    キャンセル

  • 2019/10/29 21:01

    私はRailsを使ったことがありません。

    1.既存のコードを参考にします。
    以下の記事の「CSVのアップロード機能の実装」までを参考とします。
    CSVの読み込みは行わずにfile.pathをpythonに渡せば動くのではと思います。


    RailsでCSV/Excel/OpenOfficeのアップロード機能の実装方法
    https://ruby-rails.hatenadiary.com/entry/20141120/1416483136


    2.既存のコードを参考にします。
    インスタンス変数にして動くならたぶんそれでよいと思います。

    ビューの作成とデータの受け渡し
    https://www.javadrive.jp/rails/ini/index5.html

    キャンセル

  • 2019/10/30 11:08

    ご回答ありがとうございます。
    参考にして学習いたします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る