简体   繁体   中英

Send input to python subprocess without waiting for result

I'm trying to write some basic tests for a piece of code that normally accepts input endlessly through stdin until given a specific exit command.

I want to check if the program crashes on being given some input string (after some amount of time to account for processing), but can't seem to figure out how to send data and not be stuck waiting for output which I don't care about.

My current code looks like this (using cat as an example of the program):

myproc = subprocess.Popen(['cat'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

myproc.communicate(input=inputdata.encode("utf-8"))
time.sleep(0.1)

if myproc.poll() != None:
    print("not running")
else:
    print("still running")

How can I modify this to allow the program to proceed to the polling instead of hanging after the communicate() call?

You could set a timeout in the Popen.communicate(input=None, timeout=None) function. After the timeout the process is still running and I think but you have to test it you can still send in input with communicate.

From the docs:

If the process does not terminate after timeout seconds, a TimeoutExpired exception will be raised. Catching this exception and retrying communication will not lose any output.

The child process is not killed if the timeout expires, so in order to cleanup properly a well-behaved application should kill the child process and finish communication:

You are using the wrong tool here with communicate which waits for the end of the program. You should simply feed the standard input of the subprocess:

myproc = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE)
myproc.stdin.write(inputdata.encode("utf-8"))

time.sleep(0.1)

if myproc.poll() != None:
    print("not running")
else:
    print("still running")

But beware: you cannot be sure that the output pipes will contain anything before the end of the subprocess...

I think I understand what you want here. If you know an existing command that will crash your program, you can use subprocess.Popen.wait() and it'll still block, but it'll return a tuple of the output message and the error associated with it, if any.

Then you can note the error and catch it in a try exception statement.

This was really helpful when I was working with sub processes: https://docs.python.org/3/library/asyncio-subprocess.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM