0

I'm writing a Python script which invokes python with subprocess and process several functions like the following simplified codes. (The following script doesn't work, of course.)

How can I get the return value from each function? Please help me out.

import subprocess

p = subprocess.Popen("python", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write("1+3\n")
print p.stdout.read()
p.stdin.write("2+4\n")
print p.stdout.read()
Han
  • 625
  • 2
  • 7
  • 25
  • @sparkandshine the comment is automatically made when you flag the question, you can only see the comment when you refresh the page – Tadhg McDonald-Jensen May 10 '16 at 13:39
  • Your example isn't processing functions, it looks like it's trying to evaluate a couple of _expressions_. Please clarify what it is you want to do. – martineau May 10 '16 at 13:45
  • @sparkandshine Thanks but I don't think my question is duplicate of the question you mentioned. I will refer to it for further understanding. – Han May 10 '16 at 17:10
  • unrelated: don't run python scripts as subprocesses, import the corresponding modules and call the desired functions instead. If you need to run Python code in a separate process, you could use `multiprocessing`, see [Call python script with input with in a python script using subprocess](http://stackoverflow.com/q/30076185/4279) – jfs May 10 '16 at 19:37
  • related: [Real time read from subprocess.stdout on Windows](http://stackoverflow.com/a/36904170/4279) – jfs May 10 '16 at 19:39

1 Answers1

1

If you open python non-interactively then it waits until it's read all of stdin before running the script, so your example won't work. If you write your commands and then close stdin before reading like in the following you can get the results out.

import subprocess

p = subprocess.Popen("python", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write("print 1+3\n")
p.stdin.write("print 2+4\n")
p.stdin.close()
print p.stdout.read()

Alternatively, using "-i" to force python into interactive mode:

import subprocess

p = subprocess.Popen(["python", "-i"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write("1+3\n")
print p.stdout.readline()
p.stdin.write("2+4\n")
print p.stdout.readline()
p.stdin.write("4+6\n")
print p.stdout.readline()
p.stdin.close()

This produces:

Python 2.7.10 (default, Oct 14 2015, 16:09:02) 
[GCC 5.2.1 20151010] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> >>> 4

>>> 6

>>> 10
Norgg
  • 303
  • 2
  • 6
  • 1
    Alternatively you can force python to be interactive with -i and then call `print p.stdout.readline()` after each statement. – Norgg May 10 '16 at 13:47
  • I think your comment is what the OP is looking for. – Tadhg McDonald-Jensen May 10 '16 at 13:53
  • 1
    1- you should use `p.communicate("\n".join(["print 1+3", "print 2+4"]))` instead `.write()`, `.read()` in the first code examples. 2- the second code example *if executed in a loop* may fail if `python` may return more/less than one line in response e.g., `r'print "\n"*10**6'` (the corresponding OS pipe buffer may fill up and the deadlock happens: the child will try to print to the full stdout buffer, while the parent will try to write to the full stdin buffer) – jfs May 10 '16 at 19:42