2013-04-30 24 views
28

我有,有一個小的文件結構怎麼回事,是一個程序,然後跑使用如何將獨立Python腳本集成到Rails應用程序中?

python do_work.py foo bar 

我想我的Rails用戶按一個按鈕,這個發生對他們來說,與某個地方或者上傳結果或者只是扔給他們作爲下載鏈接或類似的東西 - 輸出do_work.py(說,它的result.txt

我也想澄清,該腳本導致在文件系統上創建3個單獨的文件,其中不是文本文件(這不應該有問題,這裏也不是真正的問題)

最好的辦法是什麼?可以耙運行exec Python嗎?更重要的是,這是可行的heroku?

我在我的系統上安裝了Python,但sockmonk提供的答案似乎不起作用 - 它返回nil。請注意,其他命令如ls似乎可以正常工作。

難道這是一個權限問題?

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

順便說一句,在irb嘗試這樣的:

%x(python) 

帶來了IRB的Python的終端內部。不過無論如何它都不會採用params。

+0

我認爲這是比Rails更多的Ruby事情。似乎有幾種方法來實現這一點,在這裏找到它們 - http://stackoverflow.com/questions/2232/calling-bash-commands-from-ruby – 2013-05-05 06:08:05

回答

26

您的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模塊。

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

而且不要忘了檢查用戶輸入的數據。切勿直接將其傳遞給腳本。

+1

那麼我今天學到了一些新東西...... – 2013-05-05 07:35:56

+0

你能評論一下如何將它與ethereal/tmp/filesystem結合起來,這樣文件就保存在那裏了嗎? – 2013-05-05 07:36:28

+0

你的意思是*臨時可寫文件系統*?看到這個問題:[如何使用Heroku的臨時文件系統?](http://stackoverflow.com/questions/12416738/how-to-use-herokus-ephemeral-filesystem)。 您只需處理請求期間的文件,因爲它們可能在請求處理後被刪除。 – utapyngo 2013-05-05 13:05:41

4

部分取決於數據的格式。如果它不是太長,可以在瀏覽器中直接呈現,你可以做這樣的事情在Rails控制器:

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

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

如果你想把結果作爲一個文件發回去,看看ruby的Tempfile類來創建文件(以一種永遠不會停留的方式),以及rails的send_file和send_data命令來實現一些不同的選項通過這種方式發回結果。

+0

如果它像一個.exe怎麼辦?這會工作嗎? – 2013-05-05 01:40:52

+0

另外,我似乎無法得到在裸機應用程序上工作的示例 – 2013-05-05 01:50:39

+0

爲什麼'system()'更安全?反引用只是'system()'的別名。 – Linuxios 2013-05-07 22:52:41

3

從utapyngo答案是幾乎涵蓋了所有你需要知道的。我會回答這部分:

順便說一句,在IRB嘗試這樣的: %×(蟒蛇) INSIDE帶來了IRB的蟒蛇終端。不過無論如何它都不會採用params。

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

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

這適用於紅寶石1.8,1.9和2.0。

1

我會做類似以下的事情。

在後臺異步執行此任務。一旦結果準備好就可以將其報告給用戶。

的一種方式,你可以通過使用Open3delayed_job寶石實現這個意願。

看看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的寶石來運行這個作爲後臺任務。

你也應該有一個輪詢機制,將輪詢系統,以查看是否設置了標誌這意味着結果已經準備好,然後將其服務給用戶。

相關問題