Как подавить или перехватить вывод subprocess.run()?

Из примеров в документах на subprocess.run() кажется, что не должно быть никакого вывода из

subprocess.run(["ls", "-l"])  # doesn't capture output

Однако, когда я пытаюсь использовать его в оболочке python, распечатка распечатывается. Интересно, это поведение по умолчанию и как подавить вывод run().

Ответ 1

Вот как можно подавить вывод в порядке убывания уровня чистоты. Они предполагают, что вы находитесь на Python 3.

  1. Вы можете перенаправить на специальную цель subprocess.DEVNULL.
import subprocess

subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL)
# The above only redirects stdout...
# this will also redirect stderr to /dev/null as well
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Alternatively, you can merge stderr and stdout streams and redirect
# the one stream to /dev/null
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
  1. Если вы хотите полностью ручной метод, можете перенаправить на /dev/null, открыв дескриптор файла самостоятельно. Все остальное будет идентично методу №1.
import os
import subprocess

with open(os.devnull, 'w') as devnull:
    subprocess.run(['ls', '-l'], stdout=devnull)

Вот как захватить вывод (использовать позже или разобрать), в порядке убывания уровней чистоты. Они предполагают, что вы находитесь на Python 3.

  1. Если вы просто хотите захватить STDOUT и STDERR независимо, и вы находитесь на Python> = 3.7, используйте capture_output=True.
import subprocess

result = subprocess.run(['ls', '-l'], capture_output=True)
print(result.stdout)
print(result.stderr)
  1. Вы можете использовать subprocess.PIPE для захвата STDOUT и STDERR независимо.
import subprocess

result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
print(result.stdout)

# To also capture stderr...
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(result.stdout)
print(result.stderr)

# To mix stdout and stderr into a single string
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print(result.stdout)

ПРИМЕЧАНИЕ: по умолчанию захваченный вывод возвращается как bytes. Если вы хотите захватить как текст (например, str), используйте universal_newlines=True (или на Python> = 3.7, используйте бесконечно более понятный и простой для понимания вариант text=True - это тоже самое, что universal_newlines, но с другим именем).