繁体   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