Я использую модуль subprocess
для запуска команд из другого приложения. Я знаю, что вы можете сделать следующее
import subprocess
app = subprocess(args, stdout=subprocess.PIPE)
out, err = app.communicate()
print out
Я хотел бы, чтобы вывод отображался так, как это происходит, как предполагалось, одному большому блобу в конце. Идеи?
Проблема может заключаться в том, что команда, которую вы выполняете в подпроцессе, буферизует свой вывод: в этом случае в ответе Blender process.stdout.read(1)
не будет возвращаться до тех пор, пока выходной буфер подпроцесса не будет заполнен, в результате чего он будет очищен, и таким образом рассматривается родительским процессом.
См. этот ответ и этот для получения дополнительной информации о том, как буферизация влияет на вещи.
Вот несколько сценариев для иллюстрации:
# spew.py
import sys
import time
for i in range(10):
print 'Message no. %d' % i
#sys.stdout.flush()
time.sleep(1)
и
# runspew.py
import subprocess
import time
start = time.time()
p = subprocess.Popen(['python', 'spew.py'], stdout=subprocess.PIPE)
data = p.stdout.read(1)
print 'Elapsed time to first byte read: %.2f' % (time.time() - start)
data = p.stdout.read()
print 'Elapsed time to last byte read: %.2f' % (time.time() - start)
p.wait()
Теперь поместите оба сценария в один каталог и запустите python runspew.py
. Вы увидите что-то вроде этого:
Elapsed time to first byte read: 10.05
Elapsed time to last byte read: 10.05
Теперь удалите комментарий из sys.stdout.flush()
в spew.py
и снова python runspew.py
. Теперь вы увидите что-то вроде этого:
Elapsed time to first byte read: 0.02
Elapsed time to last byte read: 10.04
Обратите внимание, что runspew.py
не изменилось: только программа, запущенная в качестве подпроцесса. Если запущенная программа не может быть запущена небуферизованной (или часто скрытой), вам придется использовать expect
/unbuffer
, как описано в других ответах, с которыми я связан.
Я сделал реализацию оболочки Python один раз, поэтому здесь код, который я использовал для запуска команд. Он отлично работал wget
и nano
, поэтому я думаю, что код подойдет вашим потребностям:
process = subprocess.Popen(shlex.split(command), stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
while True:
output = process.stdout.read(1)
if output == '' and process.poll() != None:
break
if output != '':
sys.stdout.write(output)
sys.stdout.flush()
В принципе, вам нужно писать непосредственно в stdout
.
sys.stdout.flush()
, иначе Python продолжит буферизовать вывод.