Почему буферизируется стандартный вывод подпроцесса (перенаправляется в небуферизованный файл)? - PullRequest
9 голосов
/ 07 мая 2011

С http://docs.python.org/library/functions.html#open

Необязательный аргумент bufsize указывает желаемый размер буфера файла: 0 означает небуферизацию, 1 означает буферизацию строки, любое другое положительное значение означает использование буфера (приблизительно) этого размера,Отрицательный размер буфера означает использование системного значения по умолчанию, которое обычно буферизуется строкой для tty-устройств и полностью буферизуется для других файлов.Если опущено, используется системное значение по умолчанию.

Я передаю 0 как bufsize ниже, но без использования flush (), при выводе main_process в файл не записывается вывод.
В чем причина?

# --------------------------------- sub_process.py
import sys
import time

if __name__ == '__main__':
    print 'printed from redirect.py'
    # why is the following flush() needed? 'std-output' is (?) unbuffered...
    sys.stdout.flush() 
    time.sleep(6)


# --------------------------------- main_process.py
import subprocess
import time

if __name__ == '__main__':
    p = subprocess.Popen(
        ['python', 'sub_process.py'],
        stdout=open('std-output', 'w', 0))
    time.sleep(3)
    p.terminate()

Ответы [ 2 ]

6 голосов
/ 07 мая 2011

Использовать python с флагом -u, например ::100100

if __name__ == '__main__':
    p = subprocess.Popen(
        ['python', '-u', 'sub_process.py'],
        stdout=open('std-output', 'w'))
    time.sleep(3)
    p.terminate()
5 голосов
/ 07 мая 2011

Расширение решения Magnus Skog (+1, кстати, :)):

Ну, в общем, получается, что, когда подпроцесс будет форкировать новый процесс, он будет дублировать аргумент stdout на новый stdout подпроцесса (fileno =1) используя os.dup2 (посмотрите на subprocess.Popen._execute_child ), и это сохранит небуферизованное состояние (как делает dup2), все до сих пор хорошо, но когда будет запущен python (вподпроцесс) по умолчанию, если python не видит флаг -u, он установит буфер stdout в строковый буфер (взгляните на основную функцию python .), которая переопределит установленный вами флаг буферизациидо того.

Надеюсь, это объяснит больше поведение, которое вы видели.

...