2016-02-29 1 views
1

[Изменено]
2 варианта обработки стандартного вывода из subprocess.Popen являются stdout="a_file_name" и stdout=subprocess.PIPE.
stderr можно комбинировать с любым из них через stderr=subprocess.STDOUT.Для subprocess.stderr = STDOUT - Является ли stdout = PIPE лучше, чем stdout = "a_file_name"?

Для того, что я сейчас делаю (тестирование пуганием), мой итоговый код stdout="a_file_name" немного короче и чище.

Однако, из того, что я видел, кажется, что stdout=PIPE часто предпочитают другие, но я не уверен во всех причинах.

Если cmd используется в Popen([cmd, arg], ...) является исполнимым, который записывает вывод ошибок в stderr, является stdout=PIPE как-то лучше, чем stdout="a_file_name"?

Каковы некоторые плюсы и минусы каждого из них?

  • В моем конкретном контексте (см ниже фрагменты кода), 1 преимущество я вижу в использовании stdout=PIPE, а не stdout="a_file_name" в том, что бывший позволит мне легко пропустить запись, пустой файл.
  • В случае аварии cmd может ли 1 из 2 как-то с большей вероятностью получить весь вывод ошибки?

Хотя у меня есть мой конкретный контекст, мне было бы интересно узнать ответ (ы) для более общего случая.

Чтобы лучше объяснить свой контекст, вот мои 2 альтернативные сегменты кода:

import subprocess 
import sys 

assert sys.version_info >= (3, 3) 
    # timeout added for subprocess's wait() and communicate() in Python 3.3. 

with open('sub_proc1.outerr', 'w') as f_outerr1: 
    sub_proc1 = subprocess.Popen([cmd, args], stdout=f_outerr1, 
           stderr=subprocess.STDOUT, 
           universal_newlines=True) 
    try: 
     return_code = sub_proc1.wait(timeout=10) 
     print('*** %s CRASHED with return code: %d.' % (cmd, return_code)) 
    except subprocess.TimeoutExpired: 
     print('*** %s succeeded.' % cmd) 
     sub_proc1.kill() 

против:

... 
with open('sub_proc2.outerr', 'w') as f_outerr2: 
    sub_proc2 = subprocess.Popen([cmd, args], stdout=subprocess.PIPE, 
           stderr=subprocess.STDOUT, 
           universal_newlines=True) 
    try: 
     (sub_proc2_out, sub_proc2_err) = sub_proc2.communicate(timeout=10) 
     print('*** %s CRASHED with return code: %d.' % 
       (cmd, sub_proc2.poll())) 
     assert sub_proc2_err is None 
      # Since stderr was redirected to STDOUT, this should be None. 
     f_outerr2.write(str(sub_proc2_out or "")) 
      # Treat 'None' as an empty string). 
    except subprocess.TimeoutExpired: 
     print('*** %s succeeded.' % cmd) 
     sub_proc2.kill() 

ОРИГИНАЛЬНЫЙ ПОСТ:

TITLE: подпроцесс: Плюсы и минусы stderr = STDOUT vs. stderr = PIPE?

В 2 основные альтернативы для обработки вывода ошибок из 'subprocess.Popen' кажутся 'STDERR = STDOUT' (с 'стандартный вывод = "some_file"') и 'Stderr = PIPE'.

Для того, что я хочу сделать (тестирование пуганием), мой итоговый код «stderr = STDOUT» немного короче и чище.

Однако, из того, что я прочитал, кажется, что «stderr = PIPE» - , но я не уверен в всех причинах.

Если «Cmd» используется внешний исполняемый файл, который записывает вывод ошибок к «» STDERR, каковы плюсы и минусы использования «Stderr = STDOUT» против «Stderr = PIPE»?

...

+0

Я не думаю, что существует большая разница между этими двумя кодами, если вы ничего не делаете с выходом (кроме записи в файл) в своей тестовой программе. Если вы хотите изучить фактическую информацию о выходе (например, включить ее в ваши вызовы 'print', возможно, или проверить, что она выписывает определенную строку), тогда потребуется использовать' PIPE'. Одним из возможных преимуществ первого кода является то, что он будет чередовать потоки stdout и stderr для вас, если запущенная программа чередуется с ними. С другой стороны, вы не можете разделить эти два выхода! – Blckknght

+0

Благодарим вас за полезный комментарий, Blckknght. Я вижу, что PIPE будет лучшим вариантом, если я захочу изучить фактические данные о выходе. В моем конкретном контексте чередование потоков stdout и stderr в порядке. – Russell

+0

Ваш комментарий заставил меня понять то, чего я раньше не осознавал. Такое чередование возможно при любом способе: стандартный вывод = "a_file_name", STDERR = subprocess.STDOUT или STDOUT = subprocess.PIPE, STDERR = subprocess.STDOUT Аналогично, имеющие стандартный вывод и sterrr потоков без чередования является также возможно с любым из способов: stdout = "file_name_1", stderr = "file_name_2" или stdout = subprocess.PIPE, stderr = subprocess.PIPE – Russell

ответ

1

Запись в конкретный файл означает, что ваша программа будет иметь конфликты, если она запускается более одного раза за раз, поскольку оба процесса захотят записать в один и тот же файл. (поиск проблем с временным созданием файлов и уязвимостями безопасности)

Использование трубы означает отсутствие уникальности имени файла.

Вы заботитесь о выходе? Если нет, используйте subprocess.DEVNULL, и он отбросит выход для вас.

+0

Спасибо за ваш ответ dsh. Я вижу, что запись в конкретный файл может вызвать конфликты имен. Мой сценарий, однако, записывает все его выходные данные в подпапку на основе текущей даты/времени, поэтому это не должно быть проблемой для него: 'out_fdr = time.strftime (os.path.join (' % Y ','% m ','% d ','% H.% M.% S ')) ' Я действительно забочусь о выходе. У меня есть некоторая полезная информация из моих файлов .outerr до сих пор, например: Недостаточно памяти или Размер выделения памяти Bogus – Russell

+0

Если он работает дважды за ту же секунду, у вас будет столкновение имен в каталоге :). Если вы хотите сохранить вывод для будущего использования, то более подходящим является файл. Если вы хотите обработать вывод в своей программе, то канал более естественный. – dsh

+0

Это БОЛЬШОЙ плюс. Мой PDF-тест-тестирование обычно обнаруживает крах <1% времени, и PIPE позволяет мне писать только выходной файл stderr, если: 1. Существует запись stderr для записи. И 2. Возникнет сбой. [Первоначально я использовал stderr = "a_file_name", а затем удалил файл, если он был пуст или не было сбоев.] Спасибо. – Russell