How to Pass a String into Subprocess.Popen (Using the Stdin Argument)

How do I pass a string into subprocess.Popen (using the stdin argument)?

Popen.communicate() documentation:

Note that if you want to send data to
the process’s stdin, you need to
create the Popen object with
stdin=PIPE. Similarly, to get anything
other than None in the result tuple,
you need to give stdout=PIPE and/or
stderr=PIPE too.

Replacing os.popen*

    pipe = os.popen(cmd, 'w', bufsize)
# ==>
pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin

Warning Use communicate() rather than
stdin.write(), stdout.read() or
stderr.read() to avoid deadlocks due
to any of the other OS pipe buffers
filling up and blocking the child
process.

So your example could be written as follows:

from subprocess import Popen, PIPE, STDOUT

p = Popen(['grep', 'f'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
grep_stdout = p.communicate(input=b'one\ntwo\nthree\nfour\nfive\nsix\n')[0]
print(grep_stdout.decode())
# -> four
# -> five
# ->

On Python 3.5+ (3.6+ for encoding), you could use subprocess.run, to pass input as a string to an external command and get its exit status, and its output as a string back in one call:

#!/usr/bin/env python3
from subprocess import run, PIPE

p = run(['grep', 'f'], stdout=PIPE,
input='one\ntwo\nthree\nfour\nfive\nsix\n', encoding='ascii')
print(p.returncode)
# -> 0
print(p.stdout)
# -> four
# -> five
# ->

How do I pass a string in to subprocess.run using stdin in Python 3

Simplest possible example, send foo to cat and let it print to the screen.

 import subprocess

subprocess.run(['cat'],input=b'foo\n')

Notice that you send binary data and the carriage return.

How to use STDIN from subprocess.Popen

I was able to solve my problem by using Popen.communicate()

So some kind of pseudo code:

proc = subprocess.Popen(…)
proc.communicate(input="my_input_via_stdin")

Supply stdin input to subprocess.Popen() after execution of the process had begun ( and before it had finished )

First I think readline() is problematic here, unless the prompt from the program ends in a newline(): the program writes a prompt and is waiting for an answer while readline() is waiting for an end-of-line. I think you're going to have to use read() instead and do things a bit more low level.

To actually send something to the program, I think you can just write to process.stdin.

Have a look at pexpect (https://pexpect.readthedocs.io). I'm not sure it fits your use case, but if it does it can make life easier so it's worth the effort to find out.

One other thing to consider: many commands have an option to make it work without extra prompts, to prevent the problem you're having when run from another program. If that's the case with the program you're using, that would be by far the easiest solution.

How do I pass a string into subprocess.Popen in Python 2?

Have you tried to feed your string to communicate as a string?

Popen.communicate(input=my_input)

It works like this:

p = subprocess.Popen(["head", "-n", "1"], stdin=subprocess.PIPE)
p.communicate('first\nsecond')

output:

first

I forgot to set stdin to subprocess.PIPE when I tried it at first.

How do I write to a Python subprocess' stdin?

It might be better to use communicate:

from subprocess import Popen, PIPE, STDOUT
p = Popen(['myapp'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
stdout_data = p.communicate(input='data_to_write')[0]

"Better", because of this warning:

Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.

Send a string as a parameter in python subprocess

The problem in your code is that you are calling subprocess.Popen in the wrong way. In order to achieve what you want, as the documentation states, Popen should be called with a list of strings containing the "executable" and all the other arguments separately. More precisely, in your case it should be:

p = subprocess.Popen([filepath, os.path.abspath('.\\file.txt')], stdout=subprocess.PIPE, stdin=subprocess.PIPE)

As a side note, you should/would use .communicate(...) only when the "executable" launched "asks" for input (stdin).

How to pass subprocess control to regular stdin after using a pipe?

Unfortunately, there is no standard way to splice your own stdin to some other process's stdin for the duration of that process, other than to read from your own stdin and write to that process, once you have chosen to write to that process in the first place.

That is, you can do this:

proc = subprocess.Popen(...)  # no stdin=

and the process will inherit your stdin; or you can do this:

proc = subprocess.Popen(..., stdin=subprocess.PIPE, ...)

and then you supply the stdin to that process. But once you have chosen to supply any of its stdin, you supply all of its stdin, even if that means you have to read your own stdin.

Linux offers a splice system call (documentation at man7.org, documentation at linux.die.net, Wikipedia, linux pipe data from file descriptor into a fifo) but your best bet is probably a background thread to copy the data.



Related Topics



Leave a reply



Submit