Форум сайта python.su
Итак, задача: вызвать интерпретатор, передать ему имя файла для исполнения, по ходу его выполнения перехватывать вывод. Т.о. есть программа one.py которая вызывает two.py, которая выводит на стан.поток вывода строки, которые программа one.py должна перехватить и вывести на экран. Суть проблемы заключается в том что если two.py выведет небольшое значение , например сделает print "hello world' то оно не выведется программой one.py, так как будет ждать пока заполнится буфер или two.py сделает sys.stdout.flush(). Как раз для этого случая есть параметр bufsize, описание которого гласит:
bufsize если задан, имеет тоже значение, что и передаваемый параметр в встроенную функцию open(): 0 – без буферизации, 1 – линейная буферизация, любое другое положительное значение – использование буфера заданным размером (значение будет аппроксимировано), любое другое отрицательное значение - использование системных настроек по умолчанию, что обычно означает полную буферизацию.Но игра с параметрами не дала ожидаемого эффекта, точнее поведение вообще не менялось. Для тестирования были написаны программы one.py и two.py, последняя раз в секунду делает print строки длиною 1024 символа. Запустив one.py увидел как на экран “пачками” появляется вывод two.py причем для python 2.7 эти пачки были по 4 итерации т.е. по 4кб, для python 3.1.3 по 8кб. На Windows проблема таже.
# -*- coding: utf-8 -*-
import subprocess, sys
# python для вызова версии 2.7, python3 для вызова 3.1.3
p=subprocess.Popen(['python','./two.py'], stdout=subprocess.PIPE, bufsize=0)
sys.stdout.write('start\n')
s=True
while s:
s=p.stdout.readline()
sys.stdout.write(str(s.rstrip())+'\n')
sys.stdout.write('end\n')
# -*- coding: utf-8 -*-
from time import sleep
import sys
i=0
while True:
# строка длиной 1024
s='iteration #%000i'%i
s=s+'*'*(1023-len(s))+'\n'
sys.stdout.write(s)
i+=1
sleep(1)
Офлайн
Это Питон буферизирует. Попробуйте .
Офлайн
В two.py делайте sys.stdout.flush() после каждого sys.stdout.write(s).
one.py менять не нужно.
Офлайн
Андрей СветловЭто он знает. В первом посте упоминалось.
В two.py делайте sys.stdout.flush() после каждого sys.stdout.write(s).
one.py менять не нужно.
Офлайн
я flush() добавил - заработало.
Офлайн
возможно так!?:
bufsize регулирует буферизацию one.py (при приеме), но у two.py есть свой буфер (при отдаче).
Офлайн
Вы меня видимо не поняли. Попробую пояснить на примере.
Если вместо two.py запустить two.sh вот такого содержания:
#!/bin/sh
i=0
while true ; do
i=`expr $i + 1`
echo "iteration #$i`seq -s '+' 1012 | sed 's/[0-9]//g'`"
sleep 1
done
p=subprocess.Popen(['/bin/sh','./two.sh'], stdout=subprocess.PIPE, bufsize=0)
Отредактировано (Июнь 16, 2011 21:21:36)
Офлайн
И, чтобы уж совсем было понятно, посмотрите сюда: http://hg.python.org/cpython/file/fd6446a88fe3/Modules/main.c
Поищите там по setbuf или setvbuf и увидите, что Питону(/usr/bin/python) все равно, что вы там поставили при вызове subprocess.Popen. Он назначает либо не назначает буфер для stdout в зависимости от параметра командной строки -u.
Офлайн
> Питону(/usr/bin/python) все равно, что вы там поставили при вызове subprocess.Popen
я про то и написал в последнем сообщении
Офлайн
>я про то и написал в последнем сообщении
как то уж совсем видимо завуалированно.
Ed спасибо за подсказку с -u, совсем забыл про ключи самого интерпретатора.
Выходит что параметр bufsize это всего лишь обманка? которая есть и в python2 и в python3 при этом также упоминается в официальной документации. Не красиво как то получается, вводит людей в заблуждение
Офлайн