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()
).
If you do not have the process instance in hand to check it. Then use the operating system TaskList / Ps processes. The ps command will already be returning error code 0 / 1 depending on whether the process is found. While on windows you need the find string command.
subprocess. run() is synchronous which means that the system will wait till it finishes before moving on to the next command. subprocess. Popen() does the same thing but it is asynchronous (the system will not wait for it to finish).
Popen has a built-in method to determine if the subprocess is still running, Popen. poll(). In your code process. Popen.
To capture the output of the subprocess. run method, use an additional argument named “capture_output=True”. You can individually access stdout and stderr values by using “output. stdout” and “output.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With