How to integrate a standalone Python script into a Rails application?

dsp_099 picture dsp_099 · Apr 30, 2013 · Viewed 10.2k times · Source

I've got a program that has a small file structure going on and is then ran using

python do_work.py foo bar

I want my Rails users to press a button and have this happen for them, with the result either uploaded somewhere or just thrown to them as a download link or something of the sort - the output of do_work.py (say, it's result.txt)

I also want to clarify that the script results in the creation on the filesystem of 3 separate files, which are not text files (which shouldn't matter and isn't really the problem here)

What is the best way to go about it? Can rake run exec Python? More importantly, is this doable on heroku?

I have Python installed on my system but the provided answer by sockmonk doesn't seem to work - it returns nil. Mind you, other commands like ls seem to work.

Could it be a permissions problem?

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

Incidentally, trying this in irb:

%x(python)

Brings up the Python terminal INSIDE of irb. It will not take params for whatever reason however.

Answer

utapyngo picture utapyngo · May 5, 2013

Your index method does not work because python --version outputs its version to STDERR, not STDOUT. If you don't need to separate these streams, you may just redirect STDERR to STDOUT:

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

This call is synchronous, so after running the script (python do_work.py foo bar 2>&1), you should be able to read the files produced by it.

If the script is not able to create the files for some reason, you will now see the exception in the value variable because error messages are usually sent to STDERR.

If you want to separate STDERR from STDOUT, use the Open3 module.

Beware that the script takes some time to run, so the calls may overlap. I would use a queue here to prevent this.

And don't forget to check the data the user enters. Never pass it directly to the script.