3

I have 2 scripts script1.py and script2.py in the same folder ,script1.py calls script2.py using Popen(See code below for details),issue is that the prints coming from script2.py is not being captured in script1.py,print output and print error doesn't print a thing in the code below? what am I missing here? how do I capture the prints from script2.py?

script1.py

import subprocess
from subprocess import Popen, PIPE, STDOUT
def func1 ():
    cmd = "python script2.py"
    proc = Popen(cmd.split(' '), stdout=PIPE, stderr=PIPE)
    (output, error) = proc.communicate()
    print output
    print error

func1()
print "Done.."

script2.py

import sys
print "ERROR:port not detected"
sys.exit(29)

OUTPUT:-

C:\Dropbox>python script1.py
ERROR:port not detected


Done..
carte blanche
  • 10,796
  • 14
  • 46
  • 65
  • is there more to these scripts? "script1.py" never calls `func1()` and "script2.py" never defines a function `func1()` but does call it.. – Aaron Oct 12 '16 at 16:37
  • Thanks for pointing...missed to add a piece...updated both script1.py and script2.py – carte blanche Oct 12 '16 at 16:39
  • there is no error here then... – Aaron Oct 12 '16 at 16:41
  • issue is that the prints coming from script2.py is not being captured in script1.py,`print output` and `print error` doesn't print a thing in the code – carte blanche Oct 12 '16 at 16:43
  • I ran it through debug on my computer and it runs as expected... – Aaron Oct 12 '16 at 16:46
  • Aaron - you don't seem to get the problem – carte blanche Oct 12 '16 at 16:54
  • Change your `print` statements in `script1.py` so that it's clear when a line of console output is coming from `script1.py` and when it's coming from `script2.py`. I changed them to `print repr(output)` and `print repr(error)` and it became clear that it was working as you intend. – jez Oct 12 '16 at 16:55

2 Answers2

3

Edited answer based on comments

Looks like after the edits you made to the original question, Your code is working correctly. I just put output= in front of print statement to check that.

import subprocess
from subprocess import Popen, PIPE, STDOUT
def func1 ():
    cmd = "python script2.py"
    proc = Popen(cmd.split(' '), stdout=PIPE, stderr=PIPE)
    (output, error) = proc.communicate()
    print "output=",output
    print error

func1()
print "Done.."

** OUTPUT: **

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>> 
output= ERROR:port not detected



Done..
>>> 
Anil_M
  • 10,893
  • 6
  • 47
  • 74
  • Folks, if you are down voting, please explain why otherwise it's futile. – Anil_M Oct 12 '16 at 16:55
  • @user2125827: If this solutions solves the problem, pls consider accepting (and up-voting) to keep away unwanted down-voters. – Anil_M Oct 12 '16 at 16:57
  • 1
    Downvoted because it makes it seem like the fix was to replace `communicate` (in the question) with `stdout.read`. This does not change anything. `communicate` was already doing the same job correctly. The aspect of your answer that "fixed" the OP's problem was that you flagged the output with `'output='` and made him realize that in fact there was no problem to start with. The original OP code would also be "fixed" (i.e. prevent the OP from mistakenly believing it's not working) when you do this. – jez Oct 12 '16 at 17:01
  • using `output = proc.stdout.read()` may (if you have a huge output) overflow the buffer.. additionally if `stdout=PIPE` is defined, that buffer can overflow and block if it is not read as well as stdin. see [this](http://stackoverflow.com/a/2716032/3220135) answer as well as the comment discussion. given this if it is acceptable to read the output only once the process has terminated, it's generally preferable to use `communicate` for simplicity's sake. – Aaron Oct 12 '16 at 17:17
  • My answer was based on OP's original question which he has subsequently edited. After edits, yes I agree his code is working correctly. Hence, I've modified my answer accordingly. Although, I must mention that changing questions adds to the confusion , especially all the comments are based on previous question and previous solution. – Anil_M Oct 12 '16 at 17:25
  • @Anil_M I even suspected that must have been the case, and checked the edit history, which makes it look like `communciate` was in there from the start. I think maybe his edit happened very soon after posting, and SO must meld edits together when they happen fast. Anyway, downvote turned upside-down. – jez Oct 12 '16 at 17:29
1

your script is in fact working as intended. You likely are expecting a traceback to be printed to stderr of your subprocess, but that's not how sys.exit() works.

script1.py

import subprocess
from subprocess import Popen, PIPE, STDOUT
def func1 ():
    cmd = "python script2.py"
    proc = Popen(cmd.split(' '), stdout=PIPE, stderr=PIPE)
    (output, error) = proc.communicate()
    print output[::-1] #prints reversed message proving print is called from script1 not script2
    print error #prints nothing because there is no error text (no error was raised only system exit)
    print 'return status: '+str(proc.returncode) #this is what sys.exit() modifies
func1()
print "Done.. YAY" #done prints after call

script2.py

import sys
print "ERROR:port not detected"
sys.exit(29) #does not print traceback (or anything) only sets return code
print "Done.." #never prints because python interpreter is terminated

when script1 calls script2 as a subprocess, script2 prints it's first statement to the stdout pipe, then exits with a return code of 29. A system exit with a return code of 0 is viewed as a successful return, so unless you specifically call something that raises an error, nothing will print to the stderr pipe. the return code can however be determined from the attribute returncode of your proc.

running >python script1.py yields:

detceted ton trop:RORRE

return status: 29
Done.. YAY
Aaron
  • 10,133
  • 1
  • 24
  • 40
  • for fun, add `print 1/0` just before `sys.exit(29)` to see an example of what would happen if an exception was raised.. – Aaron Oct 12 '16 at 17:08
  • or try omitting the `sys.exit` statement entirely and see what that changes – Aaron Oct 12 '16 at 17:33