[英]How to integrate a python library into a Ruby on Rails application
[英]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设备。
我会做类似以下的事情。
在后台异步执行此任务。 一旦结果准备好,就向用户报告。
通过使用Open3和delayed_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.