Перенаправить подпроцесс stderr в стандартный вывод
Я хочу перенаправить вывод stderr подпроцесса на стандартный вывод. Постоянная STDOUT
должен сделать это, не так ли?
Тем не мение,
$ python >/dev/null -c 'import subprocess;\
subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)'
действительно выводит что-то. Почему это так, и как я могу получить сообщение об ошибке на стандартный вывод?
2 ответа
Внимательное прочтение исходного кода дает ответ. В частности, документация вводит в заблуждение, когда говорится:
subprocess.STDOUT
Специальное значение, которое (...) указывает, что стандартная ошибка должна идти в том же дескрипторе, что и стандартный вывод.
Так как стандартный вывод установлен на "по умолчанию" (-1
технически) когда stderr=subprocess.STDOUT
оценивается, stderr также устанавливается по умолчанию. К сожалению, это означает, что вывод stderr все еще идет в stderr.
Чтобы решить проблему, передайте файл stdout вместо subprocess.STDOUT
:
$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
stderr=sys.stdout.buffer)'
Или для совместимости с устаревшими версиями Python 2.x:
$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
stderr=sys.stdout.fileno())'
На самом деле, используя subprocess.STDOUT
делает именно то , что указано в документации: он перенаправляет stderr в stdout так, чтобы, например,
proc = subprocess.Popen(self.task["command"], shell=False, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = ""
while (True):
# Read line from stdout, break if EOF reached, append line to output
line = proc.stdout.readline()
line = line.decode()
if (line == ""): break
output += line
приводит к переменной output
содержащий вывод процесса из stdout и stderr.
stderr=subprocess.STDOUT
перенаправляет весь вывод stderr непосредственно на стандартный вывод вызывающего процесса, что является существенным отличием.