0

Newbie in python.

I'm trying to call a python script from a python script, for most of which I'm successful except capturing the result.

a.py

status = subprocess.call("python /hosting/apps/b.py"+" "+server+" "+port+" "+sid, shell=True)

b.py

Here in second script,I'm doing some computation and trying to pass back a variable named status using print and return

print status;
return status;

This doesn't seems to work. Is this the correct way of doing this?

Mike Laren
  • 8,028
  • 17
  • 51
  • 70
Pradeep
  • 3
  • 1
  • 2
    do you need to use subprocess? why not do `import b` from a.py? (https://docs.python.org/2/tutorial/modules.html) – Julien Spronck Mar 30 '15 at 02:28
  • 2
    Use Popen and read the stdout of the process. Instructions here: http://stackoverflow.com/questions/2502833/store-output-of-subprocess-popen-call-in-a-string – jkd Mar 30 '15 at 02:36
  • you should *import* the `b` module and call appropriate functions to get the result directly (perhaps using `threading`, `multiprocessing`, etc modules if you need multiple threads, processes) instead of running the `b.py` as an external process and capturing its output. – jfs Mar 30 '15 at 04:26

3 Answers3

1

You could use subprocess.check_output() rather than subprocess.call() to retrieve the content of the standard output (in which you have written with print and not return as BBrown noted) in a variable. This method is pretty general and is not limited to python scripts (you could call any accessible executable).

status = subprocess.check_output("python /hosting/apps/b.py"+" "+server+" "+port+" "+sid, shell=True)

However, you will retrieve the output as a string (everything that you printed during the execution of b.py) that you will need to parse. What you probably want to do is to define a function in the b.py module:

## b.py
def main(server, port, sid):
  # Do things
  return status

and call it from a.py (provided that b is in your sys.path):

## a.py
import b
status = b.main(server, port, sid)
Community
  • 1
  • 1
Geeklhem
  • 689
  • 7
  • 12
  • subprocess.check_output didnt work for me. My second script doesnt get executed. Any suggesstions? – Pradeep Mar 30 '15 at 21:37
  • I'm running python 2.4.3. Is check_output available only in later versions? – Pradeep Mar 30 '15 at 22:00
  • Indeed, `check_output` is _New in version 2.7_ according to the documentation. In this case you will need to use [`Popen`](https://docs.python.org/2.4/lib/node235.html) as @jedwards mentioned. You should upgrade if possible, this python version is almost ten years old. – Geeklhem Mar 30 '15 at 22:09
0

return won't return a value from a module (i.e. file); that's only for a function created with the def keyword. You could set the sys.stdout. See Redirect stdout to a file in Python? .

Community
  • 1
  • 1
Bennett Brown
  • 5,234
  • 1
  • 27
  • 35
0

The two options suggested in comments are probably your best bets. Here are small working examples:

Here, b.py sets status with the current time, and prints it.

b.py

import time

status = time.time()

print status

a.py (subprocess)

import subprocess

p = subprocess.Popen('python -u b.py', stdout=subprocess.PIPE)

(out,_) = p.communicate()

b_status = out

print b_status

Output:

1427685638.46

(Note, this extra space here is intended, b_status will have a trailing newline. This is something to keep in mind.)

a.py (import)

import b

b_status = b.status   # Directly access b.py's status variable

print b_status

Output:

1427685801.45
1427685801.45

Note that status is displayed twice using the second method. Once in b.py's print status and once in a.py's print b_status. Don't let it confuse you, b_status contains only the timestamp, and no trailing newline like the first approach.

(In fact, it's "displayed" twice in the first method as well, but the output from b.py is captured by a.py, which is how b_status is set when using that approach.)

In general, I think importing is a better alternative, since printing and parsing it is much more error prone.

jedwards
  • 29,432
  • 3
  • 65
  • 92
  • Thanks jedwards, I tried below with no luck `p = subprocess.Popen('python -u b.py'+' '+server+' '+port+' '+sid, stdout=subprocess.PIPE) (out,_) = p.communicate() b_status = out print b_status f = open('/tmp/test_log.log','a') f.write('\n') f.write(b_status) f.close() ` Not sure whats wrong here. But couldn't get it to work – Pradeep Mar 30 '15 at 21:47
  • 1
    Could you give us the exact error message ? – Geeklhem Mar 30 '15 at 22:12
  • If I try the exact popen code mentioned above in your answer, I get the below error `$ python a.py Traceback (most recent call last): File "a.py", line 3, in ? p = subprocess.Popen('python -u b.py', stdout=subprocess.PIPE) File "/usr/lib64/python2.4/subprocess.py", line 550, in __init__ errread, errwrite) File "/usr/lib64/python2.4/subprocess.py", line 996, in _execute_child raise child_exception OSError: [Errno 2] No such file or directory` – Pradeep Mar 31 '15 at 13:51
  • Okie, os.popen worked for me. But I encountered a new problem. When I run a.py manually everything works.. but a.py is being triggered from an application in my case. And this os.popen isn't working during this process. – Pradeep Mar 31 '15 at 15:31
  • @pradeep You may need to specify the full path to pyrthon then -- so instead of `python -u` you'd want something like `/usr/local/bin/python -u` or whatever `which python` says. – jedwards Apr 01 '15 at 00:46
  • 1
    Actually, it required full path on the child script. instead of a.py it required /hosting/apps..../a.py – Pradeep Apr 01 '15 at 13:33