簡體   English   中英

如何將獨立的Python腳本集成到Rails應用程序中?

[英]How to integrate a standalone Python script into a Rails application?

我有一個程序,它有一個小的文件結構,然后運行使用

python do_work.py foo bar

我希望我的Rails用戶按下按鈕並為他們發生這種情況,結果要么上傳到某個地方,要么只是作為下載鏈接或類似的東西拋出 - do_work.py的輸出(比如,它是result.txt

我還想澄清一下,腳本會在文件系統上創建3個獨立的文件,這些文件不是文本文件(這應該不重要,這里不是問題)

最好的方法是什么? 可以rake運行exec Python嗎? 更重要的是,這在heroku上是可行的嗎?

我在我的系統上安裝了Python,但sockmonk提供的答案似乎不起作用 - 它返回nil。 請注意,像ls這樣的其他命令似乎有效。

這可能是權限問題嗎?

def index
    value = %x( python --version )
    render :text => value
end

順便說一下,在irb嘗試這個:

%x(python)

打開irb的Python終端INSIDE。 然而,無論出於何種原因,它都不會占用。

你的index方法不起作用,因為python --version其版本輸出到STDERR,而不是STDOUT。 如果您不需要分離這些流,您可以將STDERR重定向到STDOUT:

value = %x(python --version 2>&1)

此調用是同步的,因此在運行腳本( python do_work.py foo bar 2>&1 )之后,您應該能夠讀取它生成的文件。

如果腳本由於某種原因無法創建文件,您現在將在value變量中看到異常,因為錯誤消息通常會發送到STDERR。

如果要將STDERR與STDOUT分開,請使用Open3模塊。

請注意腳本需要一些時間才能運行,因此調用可能會重疊。 我會在這里使用一個隊列來防止這種情況。

並且不要忘記檢查用戶輸入的數據。 永遠不要將它直接傳遞給腳本。

它部分取決於數據的格式。 如果它不是太長並且可以直接在瀏覽器中呈現,您可以在rails控制器中執行以下操作:

result = `python do_work.py foo bar`
render :text => result

假設結果是純ASCII文本,結果將直接進入他們的瀏覽器。 如果do_work.py的參數來自用戶,你必須首先驗證它們,所以你最終不會為自己創建一個討厭的漏洞。 在這種情況下,使用system()調用可能會更安全。

如果你想將結果作為文件發回,請查看ruby的Tempfile類以創建文件(以不會永遠存在的方式),並使用rails的send_file和send_data命令發送回結果那樣。

utapyngo的答案幾乎涵蓋了你需要知道的全部內容。 我會回答這部分:

順便說一下,在irb中嘗試這個:%x(python)打開irb的python終端INSIDE。 然而,無論出於何種原因,它都不會占用。

要將參數傳遞給python腳本,只需傳遞它即可。 例:

[fotanus@thing ~]$ python a.py 
args:
['a.py']
[fotanus@thing ~]$ irb
1.8.7 :001 > %x(python a.py foo bar)
 => "args:\n['a.py', 'foo', 'bar']\n" 

這適用於ruby 1.8,1.9和2.0。

這取決於你想要整合python腳本的深度。 有一些方法可以直接從ruby中調用python模塊。

http://www.goto.info.waseda.ac.jp/~fukusima/ruby/python-e.html

這樣可以直接從python腳本獲取輸出,而不是通過I / O設備。

我會做類似以下的事情。

在后台異步執行此任務。 一旦結果准備好,就向用戶報告。

通過使用Open3delayed_job gem,您可以實現此目的的一種方法。

看看Open3模塊中的popen3方法。

Open3.popen3([env,] cmd... [, opts]) {|stdin, stdout, stderr, wait_thr|
  pid = wait_thr.pid # pid of the started process.
  ...
  exit_status = wait_thr.value # Process::Status object returned.
}

在您的情況下,您可以將Open3.popen3語句更改為如下所示

Open3.popen3("python do_work.py foo bar"){
  ...
  # mechanism for reporting like setting a flag in database system
  # or queue system
}

注意:您應該提供python腳本的完整路徑

然后使用delayed_job gem將其作為后台任務運行。

您還應該有一個輪詢機制,它將輪詢系統以查看是否設置了標志,這意味着結果已准備就緒,然后將其提供給用戶。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM