1

I want to call something like yes "y" | foo bar, but using subprocess.Popen. Currently I use this:

yes = subprocess.Popen(['yes', '""'], stdout=subprocess.PIPE)
proc = subprocess.Popen(['foo', 'bar'], stdin=yes.stdout, stdout=subprocess.PIPE)

But, of course, this won't work on Windows. How can I do this so that it works on every platform?

Akiiino
  • 1,050
  • 1
  • 10
  • 28

2 Answers2

1
p = subprocess.Popen(['/bin/cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE )
p.stdin.write("yes\nyes\nyes")

In [18]: p.communicate()
Out[18]: ('yes\nyes\nyes', None)

You can do this in two threads of course (write in one thread and Popen instance reading in another thread).

However, that's not really safe, though:

Can someone explain pipe buffer deadlock?

Community
  • 1
  • 1
LetMeSOThat4U
  • 6,470
  • 10
  • 53
  • 93
  • My main problem is that I do not know how many times I need to answer `'yes'`, and your answer does not really help with this – Akiiino Jan 29 '16 at 09:49
0

To emulate a shell pipeline yes "y" | foo bar in Python:

#!/usr/bin/env python
from subprocess import Popen, PIPE

foo_proc = Popen(['foo', 'bar'], stdin=PIPE, stdout=PIPE)
yes_proc = Popen(['yes', 'y'], stdout=foo_proc.stdin)
foo_output = foo_proc.communicate()[0]
yes_proc.wait() # avoid zombies

To pipe input in Python (without the yes utility), you could use threads or async. I/O where input_iterator is itertools.repeat(b'y' + os.linesep.encode()).

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670