Предоставление STDOUT для stdout возвращает errno9 для subprocess.run - PullRequest
1 голос
/ 07 января 2020

Я хочу позволить пользователю моей программы указать, должен ли вывод быть подробным или нет. То есть, те подпроцессы запуска печатают весь вывод, который они генерируют или нет.

Я имел обыкновение делать:

out = subprocess.DEVNULL
if verbose:
   out = subprocess.STDOUT
subprocess.run(['ls','-la'],stderr=out,stdout=out)

Но это приводит к этой ошибке:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.8/subprocess.py", line 489, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 9] Bad file descriptor

Я смог сузить ошибку до:

subprocess.run(['ls','-la'],stdout=out)

Т.е. определение того, что вывод должен go на стандартный вывод, приводит к этой проблеме. Это было не так в ранних версиях (т. Е. <3.8) Python. </p>

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

1 Ответ

1 голос
/ 07 января 2020

Вы можете использовать опцию capture_output:

Если capture_output имеет значение true, stdout и stderr будут захвачены. При использовании внутренний объект Popen автоматически создается с stdout = PIPE и stderr = PIPE. Аргументы stdout и stderr не могут быть предоставлены одновременно с capture_output. Если вы хотите sh захватить и объединить оба потока в один, используйте stdout = PIPE и stderr = STDOUT вместо capture_output.

subprocess.run(['ls','-la'], capture_output=not verbose)

Аргумент stdout принимает значение None, subprocess.PIPE, a объект файла или дескриптор файла, но не subprocess.STD_OUT, который является просто специальным значением, которое указывает, что stderr должен go к stdout.

Вы также можете передать subprocess.DEVNULL в stdout и subprocess.STDOUT в stderr, если хотите, чтобы подпроцесс ничего не печатал и ничего не сохранял в памяти.

subprocess.run(
    ["ls", "-la"], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
)

Для подробного режима подойдет значение по умолчанию, равное None для обоих аргументов. Вы также можете передать sys.stdout на stdout и sys.stderr на stderr. Все они эквивалентны:

subprocess.run(
    ["ls", "-la"]
)
subprocess.run(
    ["ls", "-la"], stdout=None, stderr=None
)
subprocess.run(
    ["ls", "-la"], stdout=sys.stdout, stderr=sys.stderr
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...