Вы можете использовать myprocess.stdin.write()
и myprocess.stdout.read()
для связи с вашим подпроцессом, вам просто нужно быть осторожным, чтобы убедиться, что вы правильно обрабатываете буферизацию, чтобы предотвратить блокировку ваших вызовов.
Если вывод из вашегоПодпроцесс хорошо определен, вы должны иметь возможность надежно общаться с ним, используя буферизацию строки и myprocess.stdout.readline()
.
Вот пример:
>>> p = subprocess.Popen(['cat'], bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> p.stdin.write('hello world\n')
>>> p.stdout.readline()
'hello world\n'
>>> p.stdout.readline() # THIS CALL WILL BLOCK
Альтернатива этому методу дляUnix должен перевести дескриптор файла в неблокирующий режим, который позволит вам вызывать такие функции, как myprocess.stdout.read()
и возвращать данные, если таковые имеются, или вызывать IOError
, если данных нет:
>>> p = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> import fcntl, os
>>> fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
0
>>> p.stdout.read() # raises an exception instead of blocking
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 11] Resource temporarily unavailable
Это позволит вам сделать что-то вроде этого:
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
for text in textcollection:
myprocess.stdin.write(text + '\n')
while True:
myoutputtext = ''
try:
myoutputtext += myprocess.stdout.read()
except IOError:
pass
if validate_output(myoutputtext):
break
time.sleep(.1) # short sleep before attempting another read
В этом примере validate_output()
- это функция, которую вам нужно написать, которая возвращает True
, если данные, которые выдо сих пор получил весь результат, который вы ожидаете получить.