3

I would like to run a process from Python (2.4/2.5/2.6) using Popen, and I would like to give it a string as its standard input.

I'll write an example where the process does a "head -n 1" its input.

The following works, but I would like to solve it in a nicer way, without using echo:

>>> from subprocess import *
>>> p1 = Popen(["echo", "first line\nsecond line"], stdout=PIPE)
>>> Popen(["head", "-n", "1"], stdin=p1.stdout)
first line

I tried to use StringIO, but it does not work:

>>> from StringIO import StringIO
>>> Popen(["head", "-n", "1"], stdin=StringIO("first line\nsecond line"))
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/lib/python2.4/subprocess.py", line 533, in __init__
    (p2cread, p2cwrite,
  File "/usr/lib/python2.4/subprocess.py", line 830, in _get_handles
    p2cread = stdin.fileno()
AttributeError: StringIO instance has no attribute 'fileno'

I guess I could make a temporary file and write the string there -- but that's not very nice either.

1
  • It's the same question, but this one is about Python 2, where the answer is a tiny bit different from Python 3 (you don't need the "b" in front of the input string and don't need to decode the result). Commented May 7, 2016 at 6:23

2 Answers 2

8

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.

Sign up to request clarification or add additional context in comments.

2 Comments

+1 I was just part way through composing an answer suggesting the same thing.
ditto mikej :) I posted and just deleted
5

Use os.pipe:

>>> from subprocess import Popen
>>> import os, sys
>>> read, write = os.pipe()
>>> p = Popen(["head", "-n", "1"], stdin=read, stdout=sys.stdout)
>>> byteswritten = os.write(write, "foo bar\n")
foo bar
>>>

3 Comments

+1, I suggested communicate but it didn't work. Your solution works.
I tried out your "communicate" solution, and it worked! Actually, I liked it better, and I just was to accept it when it got deleted. Could you put it back?
Note that this is limited to sending a maximum of 64kB at a time, as I just discovered.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.