Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 25, 2014 14:36:20

koluna
Зарегистрирован: 2014-07-08
Сообщения: 30
Репутация: +  0  -
Профиль   Отправить e-mail  

stdin, stdout и каналы

Всем привет!

Объясните, пожалуйста, как работают stdin, stdout при выполнении подобной команды в терминале:

prog1.py | prog2.exe

В какой момент вывод prog1 попадает на ввод prog2?
Только при завершении prog1?
Есть ли различия для Linux и Windows?

Офлайн

#2 Ноя. 26, 2014 05:10:51

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

stdin, stdout и каналы

prog1.py в течении своей работы посылает строки на стандартный поток вывода (sys.stdout) которые операционной системой хранятся в специальном буфере. По завершении работы процесса запускается процесс prog2.exe на стандартный поток которого передается содержание буфера.
Таким образом передается только цельный фрагмент данных, нельзя организовать таким образом передачу информации кусочками.
Насколько я знаю в Windows и linux это работает идентично.
Однако в UNIX системах существуют UNIX Domain Socket - сокеты для межпроцессного взаимодействия. Их, пожалуй, главное отличие от каналов в возможности дву направленного обмена сообщениями, синхронно и асинхронно



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#3 Ноя. 26, 2014 05:17:53

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10014
Репутация: +  857  -
Профиль   Отправить e-mail  

stdin, stdout и каналы

koluna
Объясните, пожалуйста, как работают stdin, stdout при выполнении подобной команды в терминале:
Ну, как у python есть три потока, так и у prog2.exe есть три потока. Поток вывода python соединяется с потоком ввода prog2.exe. (Программа python пишет в то же место, откуда читает prog2.exe.)

koluna
В какой момент вывод prog1 попадает на ввод prog2?
С момента запуска.

koluna
Есть ли различия для Linux и Windows?
В данном случае нет.


JOHN_16
По завершении работы процесса запускается процесс prog2.exe на стандартный поток которого передается содержание буфера.
Нет, они сразу оба запускаются и всё, что успевает вывестись из первой программы, сразу передаётся во вторую.

[guest@localhost ~]$ python3 -c 'print(1); input(); print(2)' | cat -n
1 1
x
2 2
[guest@localhost ~]$



Отредактировано py.user.next (Ноя. 27, 2014 05:05:36)

Офлайн

#4 Ноя. 26, 2014 13:12:21

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

stdin, stdout и каналы

py.user.next
Таки да. Был не прав в своих суждениях. Все дело в буферизации вывода. Пример в linux:

#one.py
import time
for i in xrange(5):
    print 'I can do it, i will print value {}'.format(i)
    time.sleep(1)
При вызове получится что вывод отобразиться сразу, а не постепенно.
python one.py  | tee 
Если изменить исходный код так, что бы принудительно высвобождать буферы вывода:
import time, sys
for i in xrange(5):
    print 'I can do it, i will print value {}'.format(i)
    sys.stdout.flush()
    time.sleep(1)
…то вывод получится построчно.
Если мы просто организуем много вывода, то увидим работу буферизации в действии:
import time, sys
for i in xrange(500):
    print 'I can do it, i will print value {}'.format(i)
    time.sleep(0.01)

В общем признаю свою не правоту, работа с маленькими кодами сыграла со мной шутку.



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#5 Ноя. 27, 2014 05:21:05

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10014
Репутация: +  857  -
Профиль   Отправить e-mail  

stdin, stdout и каналы

JOHN_16
Все дело в буферизации вывода.

C89 (draft) 4.9.3
   At program startup, three text streams are predefined and need not
be opened explicitly --- standard input (for reading conventional
input), standard output (for writing conventional output), and
standard error (for writing diagnostic output). When opened, the
standard error stream is not fully buffered; the standard input and
standard output streams are fully buffered if and only if the stream
can be determined not to refer to an interactive device.

Сделал программу:
#include <stdio.h>
#include <unistd.h>

int main(void)
{
int i;

for (i = 0; i < 3; i++) {
printf("Test %d\n", i);
sleep(1);
}
return 0;
}

Этот выводит построчно:
[guest@localhost c]$ .ansi t.c -o t
[guest@localhost c]$ ./t
Test 0
Test 1
Test 2
[guest@localhost c]$

Этот выводит всё сразу:
[guest@localhost c]$ ./t | cat -n
1 Test 0
2 Test 1
3 Test 2
[guest@localhost c]$

То есть он для вывода в консоль включает построчную буферизацию, а для вывода в канал - полную буферизацию.

Аналогично и здесь:
[guest@localhost ~]$ python3 -c 'import time; print(1); time.sleep(2); print(2)'
1
2
[guest@localhost ~]$ python3 -c 'import time; print(1); time.sleep(2); print(2)' | cat -n
1 1
2 2
[guest@localhost ~]$
В первом случае - построчно, во втором - сразу всё.



Офлайн

#6 Ноя. 27, 2014 14:46:42

koluna
Зарегистрирован: 2014-07-08
Сообщения: 30
Репутация: +  0  -
Профиль   Отправить e-mail  

stdin, stdout и каналы

По поводу того, что процессы работают параллельно и данные передаются постоянно - понятно, спасибо за разъяснения.

Какой размер буферов stdin, stdout по умолчанию?
Можно ли изменить размер буфера и получить информацию о количестве символов в нем?
Что происходит, когда буфер stdin переполняется или близок к этому? Читал, что процесс слева от ‘|’ приостанавливается операционной системой, пока процесс справа от ‘|’ не вычитает все данные (по крайней мере для Линукс).
Не понятно, может ли буфер переполниться и потеряются ли данные или нет?

Офлайн

#7 Ноя. 28, 2014 01:33:17

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10014
Репутация: +  857  -
Профиль   Отправить e-mail  

stdin, stdout и каналы

koluna
Какой размер буферов stdin, stdout по умолчанию?
BUFSIZ - платформозависимая константа, 8 килобайт.

koluna
Можно ли изменить размер буфера и получить информацию о количестве символов в нем?
Если тебе это понадобилось в питоне, то что-то не так делаешь. В C есть функции для изменения не только размера, но и адреса.

koluna
Что происходит, когда буфер stdin переполняется или близок к этому?
Содержимое выталкивается и буфер делается пустым.

koluna
Читал, что процесс слева от ‘|’ приостанавливается операционной системой, пока процесс справа от ‘|’ не вычитает все данные
Ну, наверняка блокируется для вывода, пока читатель не прочитает.

koluna
Не понятно, может ли буфер переполниться и потеряются ли данные или нет?
Функции вывода следят за его размером. Если там есть место, они дописывают, если нет - вызывают выталкивание и обнуление и пишут в пустой.
Обычно данные не теряются, потому что буферы выталкиваются при нормальном завершении программы. При аварийном завершении могут не вытолкнуться.



Отредактировано py.user.next (Ноя. 28, 2014 01:34:17)

Офлайн

#8 Ноя. 28, 2014 12:26:24

koluna
Зарегистрирован: 2014-07-08
Сообщения: 30
Репутация: +  0  -
Профиль   Отправить e-mail  

stdin, stdout и каналы

Т. е., если программы работают нормально, то данные при обмене между программами через stdout-stdin не теряются?

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version