0

I have a base python project which can accept other python files and execute them as a sub-process. The base project accepts user input, feeds it to the sub-process which then executes code and returns a value via stdout which is fed back to the user.

In the base program I'm doing something similar to:

dataReturnValue = subprocess.check_output(['python', pythonScriptPath, json.dumps(inputParams)])

then in the subprocess I have something like this:

inputParams = sys.argv[1]
...
...
sys.stdout.write(returnValue)

The data is correctly returned, but what I'd like to do is have the data returned be limited to the returnValue. Right now it returns all print statements throughout the subprocess plus the return value. This makes sense to me since it's a form of output and print is akin to a stdout wrapper, but I'd like to better control this.

Is there a way to clear the stdout buffer just prior to my final output statement so that there are no stray prints or outputs included in the value returned from the sub-process?

Edit: I've tried doing a sys.stdout.buffer.flush(), sys.stdout.flush() just prior to the final call in hopes that it would clear out the buffer but the print statements prior still appear to be sent with the final return value.

David Torrey
  • 1,335
  • 3
  • 20
  • 43
  • If it's a python script, perhaps using `subprocess` is not the best way to go about this. If you're committed to this approach, perhaps consider printing a sentinel value that's a separator. For example `print('SENTINEL',end='')` and then do `value = dataReturnValue.split('SENTINEL')[-1]` -- But really you ideally just want to import the script and call the functions. – sytech Dec 14 '17 at 06:16

3 Answers3

1

Try this:

import sys
import os

# Your code here

with open(os.devnull, 'w') as sys.stdout:
    # Code that you don't want to be printed here
sys.stdout = sys.__stdout__

# Your code here

Edit:

I even made it into a decorator for you

import sys
import os

def silence(func, *args, **kwargs):
    def wrapper(*args, **kwargs):
        with open(os.devnull, 'w') as sys.stdout:
            result = func(*args, **kwargs)
        sys.__dict__['stdout'] = sys.__stdout__
        return result
     return wrapper

Use it on any function like this:

def test1():
    print("TEST1")

@silence
def test2():
    print("TEST2")

def test3():
    print("TEST3")

test1()
test2()
test3()

Output:

TEST1
TEST3
Myles Hollowed
  • 546
  • 4
  • 16
0

this might not be the answer you are looking for, but perhaps this is a possible workaround:

dataReturnValue = dataReturnValue.split("\n")[-1]

Gahan
  • 4,075
  • 4
  • 24
  • 44
cosmic_inquiry
  • 2,557
  • 11
  • 23
  • this one works as a workaround, at least on simple outputs, but I'm worried about if data that i want returned indeed includes a \n then it will only return a segment of the desired output and not all of it. It did get me thinking as a slight change that perhaps i could have a specific key prepended to the data output that i can split by – David Torrey Dec 14 '17 at 05:51
0

May be this can help you.

You can use subprocess Popen,PIPE to do your task.if you wish to use multiple subprocess instances here is the link

Python subprocess: how to use pipes thrice?

How to control the output ?

below command(dummy command) will generate 100 of lines , but i need only one line which have text 'Appium Started'

from subprocess import Popen,PIPE
command='appium-p 4723'
p1=Popen(command,stdout=Pipe)

return_value= 'Started Appium'

#this will store the output which command generated 
output = p3.communicate()[0]

for line in output:
    if returnvalue in line:
        print line
    else:
        pass

in the end you only get the line which you wanted i.e. Appium Started

pankaj mishra
  • 2,555
  • 2
  • 17
  • 31