views:

48

answers:

2

I have one piece of Cocoa code I wrote that takes in an XML file containing bounding boxes that are then drawn on top of a video (each box has an associated frame). The Cocoa program is meant to be run from the command line (and takes in all its parameters as command line arguments)

I can run program just fine with any XML document. However, I run into problems when I try to run the program from within a Python script. For example:

with file("test.xml") as temp:
    temp.write(doc.toprettyxml())
    # cval is my cocoa program to call, the other arguments are given to the Python script and parsed with optparser
    command = ["./cval", "-o", options.output, "-i", str(options.interval), "-s", "%dx%d" %    (options.width, options.height), "-f", str(options.frames), "-x", temp.name]
    subprocess.call(command)

Sometimes this will cause my 'cval' to fail, other times not (changing one number in the XML document can change its behavior). I can also verify it's breaking when trying to read an XML element that isn't there. Only, I can open up 'test.xml', and verify the element does in fact exist.

However, if I then run 'cval' myself (outside of the Python script) with 'test.xml', it works fine. This leads me to believe that there is something strange happening when I do 'subprocess.call', but I'm not sure what it could be. I have other Cocoa/Python mixes that do completely different tasks (i.e. not using XML) that also arbitrarily exhibit weird behavior, but are more complex in nature.

I was hoping someone might have run into this problem as well, or might know the next step in debugging this weirdness.

A: 

Perhaps try placing a "print command" statement in there, when the return code of subprocess.call indicates an error. On failure, see if there's any difference between what's being executed by subprocess and what you might run from the command line. Also, try calling subprocess.call(command, shell=True), so your command is being executed as it would in the shell (with string formatting, etc).

ars
If I print out command, I get: ['./cval', '-o', 'valtest.mp4', '-i', '0.1', '-s', '800x600', '-f', '60', '-x', 'valtest.xml']'And if I run the equivalent on the command line, it works fine: ./cval -o valtest.mp4 -i 0.1 -s 800x600 -f 60 -x valtest.xmlI tried using 'shell=True', and got the error.
Abe Schneider
Are you getting any specific error message back? You can execute the program with `subprocess.check_output`, catch the `CalledProcessError` exception (`e`) when it fails, and then print `e.output` to see what might be going wrong.
ars
I am getting an error, but as described above it originates from my Cocoa program. Somehow running the Cocoa program form subprocess.call is causing it to behave differently with the exact same input from when it is invoked from the command line. In this particular case it seems like the XML file the Cocoa program is reading (which isn't passed on the command line) isn't being parsed correctly.
Abe Schneider
Perhaps remove the `with file('test.xml') as temp` -- it doesn't seem that you're reading/writing from that file. Not sure if that would affect things, but it's the only other thing I can notice based on the information.
ars
Okay, so just edited the question, because I had left out the write in order to keep the question simple. However, when adding in the write line, I realized I should probably flush the file before calling subprocess.call. I think that fixed things.
Abe Schneider
Cool. You should probably just close the file before calling subprocess.call -- i.e. move it outside the `with` statement.
ars
The only reason I hadn't originally is that previously it was tempfile.NamedTemporaryFile(), which meant I couldn't close it without deleting the file. I changed it to a normal file for debugging purposes. Thanks for the help!
Abe Schneider
A: 

Because the code originally used temporary files, I couldn't close the file before passing it to the subprocess. However, what I should have done instead is to flush the file before subprocess.call was invoked. The inconsistent behavior likely resulted from the size of input causing automatic flushing at different thresholds.

The code should read:

with file("test.xml") as temp:
    temp.write(doc.toprettyxml())
    temp.flush()
    command = ["./cval", "-o", options.output, "-i", str(options.interval), "-s", "%dx%d" %    (options.width, options.height), "-f", str(options.frames), "-x", temp.name]
    subprocess.call(command)
Abe Schneider