2012-04-14 3 views
3

(Windows)Почему вывод подпроцесса для подпроцесса настолько ненадежный с Python?

Я написал код Python, который вызывает программу SoX (модуль подпроцесса), которая выводит прогресс на STDERR, если вы укажете его для этого. Я хочу получить статус процента от результата. Если я называю это не из сценария Python, он начинается сразу и имеет плавное продвижение до 100%.

Если я вызываю его из сценария Python, он длится несколько секунд до его запуска, а затем он чередуется между медленным выходом и быстрым выходом. Хотя я читаю char char, иногда там вырывает большой блок. Поэтому я не понимаю, почему в другое время я могу наблюдать за тем, чтобы персонажи становились все больше друг за другом. (Он генерирует 15KiB данных в моем тесте, между прочим.)

Я тестировал то же самое с mkvmerge и mkvextract. Они также выводят проценты. Чтение STDOUT происходит гладко.

Это настолько ненадежно! Как я могу сделать чтение потока stderr sox более плавным и, возможно, предотвратить задержку в начале?


Как звонить и читать:

process = subprocess.Popen('sox_call_dummy.bat', stderr = subprocess.PIPE, stdout = subprocess.PIPE) 
while True: 
    char = process.stderr.read(1).encode('string-escape') 
    sys.stdout.write(char) 
+0

Какое значение имеет значение bufsize? Вы можете показать свой фрагмент подпроцесса? – jdi

+0

Zero (по умолчанию). Но я только что протестировал 1, 1024, 8 * 1024, 16 * 1024, 160 * 1024, это то же самое с каждым значением. – rynd

+0

Отправьте пример кода, как вы звоните и читаете свой процесс. – jdi

ответ

1

В соответствии с этим тесно связаны теме: Unbuffered read from process using subprocess in Python

process = subprocess.Popen('sox_call_dummy.bat', 
       stderr = subprocess.PIPE, bufsize=0) 
while True: 
    line = process.stderr.readline() 
    if not line: 
     break 
    print line 

Поскольку вы не читаете стандартный вывод, я не думаю, что вам нужно труба для него.

Если вы хотите попробовать чтение полукокса по полукокса, как в исходном примере, попробуйте добавить флеш каждый раз:

sys.stdout.write(char) 
sys.stdout.flush() 

Промывка стандартный вывод каждый раз, когда вы пишете, ручной эквивалент отключение буферизации для питона процесс: python.exe -u <script> или установка переменной env PYTHONUNBUFFERED=1

+0

Я создаю трубку для stdout из-за ошибки, когда я пытаюсь запустить скрипт, если нет окна консоли, а окна IDLE GUI. – rynd

+0

@rynd: Хорошо, тогда добавьте его обратно всеми средствами, если что-то его читает. – jdi

+0

Проблема остается. Если я посмотрю загрузку процессора подпроцесса, я вижу, что sox работает с 90% нагрузкой, в то время как мой скрипт все еще имеет задержку. Почему read() не работает в данный момент? Затем первый выход (информация, не связанная с прогрессом) выводится медленно. – rynd

Смежные вопросы