Найти - Пользователи
Полная версия: bufsize в subprocess.Popen - баг или фича ? Давайте разберемся.
Начало » Python для экспертов » bufsize в subprocess.Popen - баг или фича ? Давайте разберемся.
1 2
Андрей Светлов
Ни разу не вводит. Укажите bufsize побольше и запустите two.py с ключем -u
Это же разные стороны соединения.
Ed
JOHN_16
Выходит что параметр bufsize это всего лишь обманка? которая есть и в python2 и в python3 при этом также упоминается в официальной документации. Не красиво как то получается, вводит людей в заблуждение
Нет, не выходит. subprocess действительно устанавливает буфер stdout в соответствии со значением bufsize, но запущеный процесс об этом не может знать, поскольку нет стандартного способа об этом сказать. Вы путаете subprocess API и поведение python, запущенного как процесс. Они по большому счету никак не связаны.
JOHN_16
Хорошо, посмотрим на это с такой стороны, вот код в two.py выводит через секунду строку длиной 1024 символа, ну это можно сказать 1кб.
Так вот, Что нужно исправить что бы получилось что бы запустив one.py на экран отправлялись“пачки” вывода длиной в 8 итераций т.е. 8 кб ?
Ed
Нужно в one.py читать по 8 кб. Вот так:
s=p.stdout.read(8*1024)
Это же блокирующее чтение, будет ждать пока не прочитает.
JOHN_16
В общем я прихожу к выводу тчо не понимаю до сих пор.
EdВнимательно прочел что вы написали до этого, и вот не совсем понимаю зачем тогда нужен этот параметр т.е. как его можно именно применять??? можете подсказать по этому вопросу?
Ed
Параметр нужен, чтобы установить размер буфера для std* потоков процесса.
А вот дальнейшее зависит от процесса, который вы запускаете. Я специально показал пример с шеллом, который ничего с размером буфера не делает. А Питон делает.

Чтобы окончательно понять что тут к чему я бы посоветовал написать маленькую программку на Си и запускать ее. Тогда вы окончательно прочуствуете, что процесс получает тот буфер, который установил ему subprocess.Popen. Но если внутри процесса вы захотите его сменить, то сможете это сделать. Питон именно так и поступает.
JOHN_16
попробовал написать аналогичную программку , так как в C не силен то получилось не слишком красиво, код loop_print.c :
#include <stdio.h>
int main() {
char *base="************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************";
int i=100;
for (i; i<150; i++){
printf("%i%s\n",i, base);
sleep(1);
}
return 0;
}
В итоге так
1) поигрался с bufsize на примере скрипта на шеле, независимо от него вывод идет построчно.
2)поигрался с bufsize на примере программы на C, независимо от него вывод идет по 4 итерации = 4кб. компилировал банально
john_16@linux-home:~/C> gcc –version
gcc (SUSE Linux) 4.5.1 20101208
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

john_16@linux-home:~/C> gcc -o loop_print loop_print.c

Я что то не так на C написал? В общем где я ошибся?? уж больно хочется разобраться в этом вопросе.
Ed
Почитавши сорцы и маны я пришел к такой картинке:
При запуске программы на си открывается stdout со своим буфером. Видимо в вашем случае этот буфер равен 4кб.
Subprocess использует свою буферизацию в соответствии со значением bufsize. При этом для открытия файлов он использует io.open, причем для дескрипторов, приаттаченых к терминалу(наш случай?) он использует построчную буферизацию.
То есть получается, что если в самой программе буферизация отключена, то, несмотря на значение bufsize поток у нас буферизируется построчно, что мы и наблюдаем. Если же в самой программе буферизация включена, то мы получаем ваши 4 итерации, поскольку буфер 4килобайтный.
Это пока мои домыслы, поскольку времени не было попробовать.

Чтобы убедиться в частичной правильности моих выводов вы можете использовать для вывода не потоковые функции, а те, которые работают с дескрипторами(write с дескриптором STDOUT_FILENO, в данном случае). Либо с помощью setvbuf убрать буфер с потока stdout. Скорее всего в результате в вашем one.py получите построчный вывод, как и в случае с shell или python -u.
Потом, если захотите, можно будет подумать о том, как уйти от построчной буферизации и получить то, что вы хотели - при изменении bufsize в вызове subprocess.Open получить изменение в выводе.

PS: Вполне возможно что это частично или полностью бред. Нужно пробовать.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB