Метод communicate
объектов subprocess.Popen
может быть вызван только один раз.Он отправляет введенные вами данные процессу , а читает все выходные данные stdout и stderr.Под словом «все» я подразумеваю, что он ожидает завершения процесса, чтобы он знал, что у него есть все выходные данные.После возврата communicate
процесс больше не существует.
Если вы хотите использовать communicate
, вам нужно либо перезапустить процесс в цикле, либо присвоить ему одну строку, которая all вход от генератора.Если вы хотите осуществлять потоковую связь, посылая данные побитно, вам не нужно использовать communicate
.Вместо этого вам нужно будет написать в p.stdin
при чтении из p.stdout
и p.stderr
.Делать это сложно, потому что вы не можете сказать, какой вывод вызван каким вводом, и потому что вы можете легко столкнуться с тупиками.В этом вам могут помочь сторонние библиотеки, например Twisted.
Если вы хотите сделать это в интерактивном режиме , отправив некоторые данные, а затем ожидая и обрабатывая результат, прежде чем отправлять большеданные, все становится еще сложнее.Возможно, вам следует использовать стороннюю библиотеку, например pexpect
.
Конечно, если вам удастся просто запустить процесс внутри цикла, это будет намного проще:
cmd = ['intersectBed', '-a', 'stdin', '-b', bedfile]
for entry in my_entry_generator:
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = p.communicate(input='\t'.join(entry) + '\n')[0]
print output