How to integrate a standalone Python script into a Rails application?
我有一个程序正在运行,它有一个小的文件结构,然后用
1 | python do_work.py foo bar |
我想让我的Rails用户按下一个按钮,让他们这样做,结果要么上传到某个地方,要么作为下载链接或者类似的东西扔给他们——EDOCX1的输出(比如说,它是
我还想澄清一下,脚本会在文件系统上创建3个独立的文件,这些文件不是文本文件(这不重要,也不是真正的问题)
最好的方法是什么?rake可以运行exec python吗?更重要的是,这在Heroku上可行吗?
我的系统上安装了python,但sockmamk提供的答案似乎不起作用——它返回零。注意,其他命令,如
可能是权限问题吗?
1 2 3 4 | def index value = %x( python --version ) render :text => value end |
顺便说一下,在
1 | %x(python) |
打开IRB内部的python终端。但是,无论出于什么原因,它都不会获取参数。
您的
1 | value = %x(python --version 2>&1) |
此调用是同步的,因此在运行脚本(
如果脚本由于某种原因无法创建文件,您现在将在
如果要将stderr与stdout分开,请使用open3模块。
请注意,运行脚本需要一些时间,因此调用可能会重叠。我会在这里排队以防发生这种情况。
别忘了检查用户输入的数据。千万不要直接传递给脚本。
这部分取决于数据的格式。如果它不太长,可以直接在浏览器中呈现,您可以在Rails控制器中执行类似的操作:
1 2 | result = `python do_work.py foo bar` render :text => result |
假设结果是纯ASCII文本,结果将直接进入浏览器。如果要进行工作的参数来自用户,则必须首先验证它们,这样您就不会最终为自己造成严重的漏洞。在这种情况下,使用System()调用可能更安全。
如果您想将结果作为一个文件发送回来,请查看Ruby的tempfile类来创建该文件(以一种不会永远保留的方式),以及Rails的send_file和send_data命令,以获得一些不同的选项来以这种方式发送结果。
Utapyngo的答案几乎涵盖了你需要知道的所有内容。我会回答这一部分:
incidentally, trying this in irb:
%x(python)
Brings up the python terminal INSIDE of irb. It will not take params for whatever reason however.
要将参数传递给Python脚本,只需传递它。例子:
1 2 3 4 5 6 7 8 | [fotanus@thing ~]$ python a.py args: ['a.py'] [fotanus@thing ~]$ irb 1.8.7 :001 > %x(python a.py foo bar) =>"args: ['a.py', 'foo', 'bar'] " |
这适用于Ruby1.8、1.9和2.0。
我会做如下的事情。
在后台异步执行此任务。一旦结果准备好,就向用户报告。
有一种方法可以通过使用open3和delayed-job-gem来实现这一点。
看看open3模块中的popen3方法。
1 2 3 4 5 | 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. } |
在您的案例中,您可以将
1 2 3 4 5 | Open3.popen3("python do_work.py foo bar"){ ... # mechanism for reporting like setting a flag in database system # or queue system } |
注意:应该给出python脚本的完整路径
然后使用延迟的作业gem将其作为后台任务运行。
您还应该有一个轮询机制,该机制将轮询系统,以查看是否设置了标志,这意味着结果已经准备好,然后将其提供给用户。
这取决于您希望集成Python脚本的深度。有一些方法可以直接从Ruby调用Python模块。
网址:http://www.goto.info.waseda.ac.jp/~fukusima/ruby/python-e.html
这将使您受益于直接从Python脚本获得输出,而不是遍历I/O设备。