2016-09-27 2 views
2

Когда я пишу питон скрипт outer.py, содержащегопитон подпроцесс: порядок вывод изменений при использовании subprocess.PIPE

p = subprocess.Popen(['./inner.py']) 
print('Called inner.py without options, waiting for process...') 
p.wait() 
print('Waited for inner.py without options') 

p = subprocess.Popen(['./inner.py'], stdout=subprocess.PIPE) 
print('Called inner.py with PIPE, communicating...') 
b_out, b_err = p.communicate() 
out = b_out.decode('utf8') 
print('out is "{}"'.format(out)) 

И в inner.py содержащего

print("inner: Echoing Hallo") 
p = subprocess.Popen(['echo', 'hallo']) 
print("inner: Waiting for Echo to finish...") 
p.wait() 
print("inner: Waited for Echo") 

я получаю следующее при вызове outer.py из a:

Called inner.py without options, waiting for process... 
inner: Echoing Hallo 
inner: Waiting for Echo to finish... 
hallo 
inner: Waited for Echo 
Waited for inner.py without options 

Called inner.py with PIPE, communicating... 
out is "hallo 
inner: Echoing Hallo 
inner: Waiting for Echo to finish... 
inner: Waited for Echo 
" 

Почему, звонив inner.py с stdout=subprocess.PIPE, появляется ли «hallo» перед «внутренним: Echoing Hallo» на захваченном выходе?

+0

не может воспроизвести на моем Mac - однако мне пришлось добавить инструкции shebang и import, чтобы код работал в первую очередь. Пожалуйста, укажите полный пример, а также используемую вами операционную систему. –

+1

Похоже, что это может быть буферизация по стандарту из inner.py. Можете ли вы попробовать отключить буферизацию, например, с установкой PYTHONUNBUFFERED? Дополнительные методы, перечисленные здесь: http://stackoverflow.com/a/107717/1062499 – wildwilhelm

+0

Общайтесь не с одним действием цикла и всегда возвращаемой строкой, а не с выводами! – dsgdfg

ответ

1

Я предположил бы, что, по некоторым причинам (в связи с трубами против TTYs см this comment), выход процесса inner.py Python небуферизован первый раз, когда вы называете его, и буферным во второй раз вы называете его. В первый раз, с небуферизованным выходом, вы получите результат в ожидаемом порядке, написанном на вашем tty. Во второй раз, с буферизацией, вывод команды echo сначала сбрасывается (поскольку echo запускается и завершается), а затем весь вывод из процесса inner.py появляется сразу, когда python завершается. Если вы отключите буферизацию вывода для inner.py, вы должны получить тот же результат в обоих случаях.

Отключить буферизацию вывода, установив переменные окружения PYTHONUNBUFFERED, или позвонив по телефону питона с помощью переключателя -u или явного вызова sys.stdout.flush() после каждого print (или print(..., flush=True) на Python 3).

Различия между поведением труб и ttys выглядят как general behaviour of stdio: вывод в ttys буферизируется по строке (поэтому в вашем коде, который читается по строкам, он выглядит небуферизованным), тогда как вывод на трубы буферизуются.