Reputation: 5757
I need to call a shellscript from python. The problem is that the shellscript will ask a couple of questions along the way until it is finished.
I can't find a way to do so using subprocess
! (using pexpect
seems a bit over-kill since I only need to start it and send a couple of YES to it)
PLEASE don't suggest ways that requires modification to the shell-script!
Upvotes: 5
Views: 41032
Reputation: 1
I don't know why the answer for this question is accepted as an answer, but you need to flush the stdin
rather than closing it if the script is still running. Not to mention it, its better to redirect the stderr
to stdout
.
#main.py
import subprocess
cmd = ['shellscript.sh']
shellscript = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,stdin=subprocess.PIPE)
for line in shellscript.stdout:
print(str(line.strip()))
returncode = shellscript.wait()
print(f"Process ended with the return code of {returncode}.")
This small modification allows you to have more control over the stdout
and stdin
without having to worry about the stderr
.
For stdin
, you can directly write to it, but the accepted answer has the wrong method of usage for shellscript.returncode
. Its better to use shellscript.wait()
until the process ends. The return value of wait()
is the self.returncode
of the process.
shellscript.stdin.write("yes\n")
shellscript.stdin.flush()
returnCode = shellscript.wait()
print(f"Process exited with the return code of {returnCode}.")
This is my take on the question. There is multiple ways of achieving your usage using the documentation of the subprocess
module. Here's the link to the documentation of the subprocess module.
Upvotes: 0
Reputation: 5974
Using the subprocess
library, you can tell the Popen
class that you want to manage the standard input of the process like this:
import subprocess
shellscript = subprocess.Popen(["shellscript.sh"], stdin=subprocess.PIPE)
Now shellscript.stdin
is a file-like object on which you can call write
:
shellscript.stdin.write("yes\n")
shellscript.stdin.close()
returncode = shellscript.wait() # blocks until shellscript is done
You can also get standard out and standard error from a process by setting stdout=subprocess.PIPE
and stderr=subprocess.PIPE
, but you shouldn't use PIPEs
for both standard input and standard output, because deadlock could result. (See the documentation.) If you need to pipe in and pipe out, use the communicate
method instead of the file-like objects:
shellscript = subprocess.Popen(["shellscript.sh"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = shellscript.communicate("yes\n") # blocks until shellscript is done
returncode = shellscript.returncode
Upvotes: 8