0

I am trying to run a python script from ruby method. I am running this method as a rake task within a Rails app. I am using the solution mentioned here:

def create
    path = File.expand_path('../../../../GetOrders', __FILE__)
    output = `"python2 " + path + "/parse.py"`
    print output
    str = JSON.parse(output)
    print str
end

EDIT: This works:

    output = `python2 #{path}/parse.py`

EDIT2: Using the python script i am trying to pass a list of dictionaries to the ruby function. The python script looks something like:

import xml.etree.ElementTree as ET
import json

def parse():
    tree = ET.parse('response.xml')
    root = tree.getroot()
    namespaces = {'resp': 'urn:ebay:apis:eBLBaseComponents'}
    order_array = root.find("resp:OrderArray", namespaces=namespaces)
    detailsList = []
    for condition:
        details["key1"] = value1
        details["key2"] = value2
    detailsList.append(details)
    output = json.dumps(detailsList)
    return output

print parse()

Could someone explain what i am doing wrong and how can I fix this. Thanks

Community
  • 1
  • 1
nish
  • 6,952
  • 18
  • 74
  • 128
  • can you run it directly on the command line? – thorsten müller Feb 08 '14 at 18:40
  • @thorstenmüller : yes, the python script executes fine from command line – nish Feb 08 '14 at 18:40
  • [`Kernel#``](http://ruby-doc.org/core-2.1.0/Kernel.html#method-i-60) don't take its argument as string. – Arup Rakshit Feb 08 '14 at 18:46
  • 2
    the output of the script may not be sent to stdout? could that be possible? – thorsten müller Feb 08 '14 at 18:49
  • could you try to use `print` instead of `return`? – thorsten müller Feb 08 '14 at 19:03
  • @thorstenmüller: The `print` statement in `parse.py` prints the desired result. – nish Feb 08 '14 at 19:04
  • 1
    no, something like `print parse()` in the last line of parse.py – thorsten müller Feb 08 '14 at 19:08
  • @thorstenmüller: I replace `parse` with `print parse()`. It gives a weird error. updated in the question. – nish Feb 08 '14 at 21:11
  • This question is all over the place. nish, first, make a simple Hello World python script that prints something and verify you can run it from the console. Next, write a very simple Ruby program that calls it by putting the correct command in backticks. Then post both programs and tell us the exact error message. It looks like you are in a Rails app or something, and you didn't actually give us the error message, just a stack trace. – David Grayson Feb 08 '14 at 21:21
  • Remove the call to JSON.parse in the Ruby because that is apparently raising an exception. Just do `puts output.inspect` to see exactly what output Ruby is getting from the Python program. – David Grayson Feb 08 '14 at 21:24
  • @DavidGrayson: I have updated the question. Hope it makes more sense now. – nish Feb 08 '14 at 21:42
  • 2
    OK, so now you have narrowed this problem down to an issue in your python program. It is no longer about Ruby. I think you should ask a new question on this site that is just about the Python. Show the full program, the actual output, and the expected output. You are probably just using the Python JSON libary incorrectly. If Ruby is going to be parsing the JSON, then Python should output JSON directly instead of trying to parse it at all, which it seems like dumps might be doing. There is no reason to be parsing JSON on the Python and Ruby side as far as I know. – David Grayson Feb 08 '14 at 22:36
  • @DavidGrayson: I had put a lot of print statements in my python script. And those were getting prepended to the JSON I actually wanted to pass. – nish Feb 08 '14 at 23:26
  • It'll be hard to help you debug the python unless you post the actual code. What you've given in the question isn't even syntactically correct. – Alp Feb 09 '14 at 00:28

3 Answers3

1

You are calling this exact line on the shell:

"python2 -path- /parse.py"

which the shell interprets as a single command: python2 (with a space at the end).

Try using string interpolation, which works with the backtick operator:

output = `python2 #{path}/parse.py`
whatyouhide
  • 15,897
  • 9
  • 57
  • 71
  • I already tried this: output = `python2 #{path}/parse.py`. It does not print anything. mentioned in the edits of the question – nish Feb 08 '14 at 18:48
  • @nish Are you sure your Python script *does* print something on the standard output? – whatyouhide Feb 08 '14 at 18:49
  • edited. Sry for posting wrong one earlier. The python script works fine. – nish Feb 08 '14 at 19:05
1

Imagine typing this exact string:

"python2 " + path + "/parse.py"

into your shell (e.g. bash). It would look for a program named "python2 " and give it four arguments

+
path
+
/parse.y

You can't put arbitrary Ruby code inside a backtick string the same way you can't put arbitrary code in normals strings. You must use string interpolation.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
1

When you do this:

output = `python2 #{path}/parse.py`

output will be assigned the standard output of the python script, but that script isn't writing anything to standard output; the json data that's the return value of the parse() call is simply discarded. You seem to be expecting the execution of the script to have a "return value" that's the return value of the script's last expression, but that's not how processes work.

You probably want to replace the parse() call at the end of the script with print parse().

Alp
  • 2,766
  • 18
  • 13