8

file sp.py:

#!/usr/bin/env python3
s = input('Waiting for your input:')
print('Data:' + s)

file main.py

import subprocess as sp
pobj = sp.Popen('sp.py',stdin=sp.PIPE,stdout=sp.PIPE,shell=True)
print(pobj.stdout.read().decode())
pobj.stdin.write(b'something...')
print(pobj.stdout.read().decode())

main.py will block in the first pobj.stdout.read(), because sp.py is waiting for me.
But if I want to process the string 'Waiting for you input:' first, how can I know whether sp.py is waiting for me ?
In other words, I want the pobj.stdout.read() to return when sp.py is waiting (or sleeping because of time.sleep()).

Richard Tsai
  • 101
  • 1
  • 4
  • Have you tried to use `pobj.communicate`, as advised in the [subprocess doc](http://docs.python.org/library/subprocess.html)? – Pierre GM Aug 29 '12 at 14:24
  • This question may be helpful: http://stackoverflow.com/questions/375427/non-blocking-read-on-a-subprocess-pipe-in-python – Vaughn Cato Aug 29 '12 at 14:33
  • @PierreGM Thanks a lot. `communicate`will terminate the subprocess after being called. – Richard Tsai Aug 30 '12 at 02:02
  • @VaughnCato Thanks a lot. It's helpful, but how can I distinguish between "still working" and "waiting for input" ? – Richard Tsai Aug 30 '12 at 02:07
  • 1
    Note that a process accepts input even if it isn't waiting for it, so you could write to pobj.stdin first, and it will get that input whenever it tries to read it. – Vaughn Cato Aug 30 '12 at 04:46

1 Answers1

2

Okay, I've worked it out. My code is based on Non-blocking read on a subprocess.PIPE in python (Thanks, @VaughnCato)

#!/usr/bin/env python3
import subprocess as sp
from threading import Thread
from queue import Queue,Empty
import time

def getabit(o,q):
    for c in iter(lambda:o.read(1),b''):
        q.put(c)
    o.close()

def getdata(q):
    r = b''
    while True:
        try:
            c = q.get(False)
        except Empty:
            break
        else:
            r += c
    return r

pobj = sp.Popen('sp.py',stdin=sp.PIPE,stdout=sp.PIPE,shell=True)
q = Queue()
t = Thread(target=getabit,args=(pobj.stdout,q))
t.daemon = True
t.start()

while True:
    print('Sleep for 1 second...')
    time.sleep(1)#to ensure that the data will be processed completely
    print('Data received:' + getdata(q).decode())
    if not t.isAlive():
        break
    in_dat = input('Your data to input:')
    pobj.stdin.write(bytes(in_dat,'utf-8'))
    pobj.stdin.write(b'\n')
    pobj.stdin.flush()
Community
  • 1
  • 1
Richard Tsai
  • 101
  • 1
  • 4