2016-07-18 2 views
0

У меня есть следующий фрагмент кода для чтения данных из дочернего процесса в виде его сгенерированного и записи в файл.python subprocess pipe небуферизованное поведение

 
from subprocess import Popen, PIPE 
proc = Popen('..some_shell_command..', shell=True, stdout=PIPE) 
fd = open("/tmp/procout", "wb") 
while True: 
    data = proc.stdout.read(1024) 
    if len(data) == 0: 
     break 
    fd.write(data) 
fd.close() 

По умолчанию bufsize 'Popen' равен 0 => без буферизации. Что произойдет, если по какой-то причине операция записи в файл испытывает огромную задержку?

  • Предполагая, что дочерний процесс должен производить 500 ГБ данных, все эти данные сохраняются в памяти до тех пор, пока родитель не прочитает их все? (OR)
  • Будет ли дочерний процесс ждать 1024 байта данных, которые должен быть прочитан родителем, прежде чем записывать следующие 1024 байта в stdout? (OR)
  • Будет ли процесс дочернего процесса ждать, когда буфер буфера OS заполняется, и как только родитель читает, ребенок снова возобновляет запись? (OR)
  • ??

ответ

1

Отвечая на вопросы:

  • Нет, это не будет храниться в памяти. Детский процесс будет зависеть от операции write после превышения предела pipe-max-size (cat/proc/sys/fs/pipe-max-size);
  • Детский процесс будет писать около 1 М до того, как он застрянет, пока родительский процесс не прочитает блок данных. После этого дочерний процесс будет записывать следующие 1024 байта последовательно так же быстро, как они будут прочитаны;
  • Да, в случае блокировки ввода-вывода процесс будет заблокирован операционной системой, когда вызывается write syscall. В случае неблокирующего IO я надеюсь, что write syscall вернет EAGAIN или другую системную ошибку.

Так что приложение будет застревать при вызове write Системный вызов, ожидающий наличия буфера канала. Это не значит, что он повесится. Например, если приложение реализует какую-то внутреннюю очередь и имеет более одного потока, оно может продолжать работать и добавлять любые данные в свою очередь, в то время как ответный поток будет ждать буфера.