0

I have a very beginner question. I'm trying to do the following where I need to get a list from another Python script using subprocess.

level 1 :

#!/usr/bin/python

import sys
import os

def run(a):
    print "running"
    return a

#if __name__ == "__main__":
    run(str(sys.argv[1]))

level 0 :

import sys
import os
import subprocess

output = subprocess.check_output(['python','level1.py','test'])
print output

However, when I run this, the output prints out "running" instead of the value stored in variable a.

I was wondering how I can get the value of a instead of all the print statements.

martineau
  • 119,623
  • 25
  • 170
  • 301
eoses
  • 15
  • 3
  • 2
    Exit status is a 7-bit integer. You don't want to try to use it for an arbitrary return value. Printing to stdout, and capturing stdout, is the Right Thing. If "running" is a log message, as opposed to output, you should be printing it to stderr to keep it out-of-band. – Charles Duffy Aug 25 '17 at 18:35
  • Like Charles said, replace your "return a" with "print a" and you should be good. You also want to remove the "print running" statement since thats not what you're trying to catch – AllenMoh Aug 25 '17 at 18:37
  • Thanks for the replies guys. I'll give that a shot. – eoses Aug 25 '17 at 19:01
  • Since you commented out the `if __name__` statement then the rules of indentation say that your call to `run()` will be part of the function and nothing will be executed (since you have a `return` before it). – cdarke Aug 25 '17 at 19:06

5 Answers5

0

Take a look at https://stackoverflow.com/a/7975511/3930971

You are using another system process to run the script, it does not tell the rest of your system of the value returned the call to run(). All the rest of the system sees is what is directed to output (stdout, stderr), your current script only sends "running" to output, so that is what subprocess sees.

If you decided to treat it as module and import it, you could get return values of functions.

chicocvenancio
  • 629
  • 5
  • 14
0

Once you hit the return statement in the run function, that file finishes and no more code is executed: You could even do:

def run(a):
  print "Running: ", a
srattigan
  • 665
  • 5
  • 17
0

level1.py never prints the value returned by run(). Change to:

print(run(sys.argv[1]))

BTW, there's no need to use str(), since the elements of argv are always strings.

Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Try this:

level1.py

import sys
import os

def m1(a):
    for elements in a:
        print(elements)

level0.py

import level1

a = ['first','second','third']
output = level1.m1(a)
print(output)
Mohd
  • 5,523
  • 7
  • 19
  • 30
0

Part of the problem is the commented-out line in leve1.py:

#if __name__ == "__main__":

is messing things up because it causes the run(str(sys.argv[1])) to be considered the last line of the run() function—which is never executed because of the return statement right before it.

Another is you can only get the sub-process's return code from subprocess.check_output which is a 7-bit integer value.

One way around that limitation on the result returned is to use pipes to capture whatever the called process prints or otherwise sends to its sys.stdout (and stderr as shown below). First modify run() to print its result, not return it.

level1.py:

import sys
import os

def run(a):
    print "running"
    print a

run(str(sys.argv[1]))

Then modify the driver to get and display what was output to stdout:

level0.py:

import sys
import os
import subprocess

kwargs = dict(stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
              universal_newlines=True)
with subprocess.Popen(['python','level1.py','test'], **kwargs).stdout as output:
    for line in output:
        print line,

Output:

running
test

Another way to do it would be to using the multiprocessing module which would allow you to pass back arbitrary values (not just strings).

martineau
  • 119,623
  • 25
  • 170
  • 301