Почему мы потеряли стандартный вывод из терминала после запуска subprocess.check_output (xyz, shell = True)? - PullRequest
0 голосов
/ 16 декабря 2018

У меня есть строка bash:

$ printf '  Number of xml files: %s\n' `find . -name '*.xml' | wc -l`
  Number of xml files: 4
$

Когда я запускаю его таким образом из python останов интерпретатора Python и мой терминал больше не имеет stdout ::

$ ls
input aa bb
$ python
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
>>>
>>> import subprocess
>>> cmd = "printf  'xml files: %s\n' `find . -name '*.xml' | wc -l`"
>>> subprocess.check_output(['/bin/bash', cmd], shell=True)
$ ls  # stdout is not seen any more I have to kill this terminal
$

Очевидно, что вопрос здесь не в том, как заставить этот bash работать с python ::

>>> import subprocess
>>> cmd = "printf  'xml files: %s\n' `find . -name '*.xml' | wc -l`"
>>> out = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE)
>>> print(str(out.stdout, 'utf8'))
xml files: 4

>>> 

Две следующие проблемы Нет вывода из subprocess.check_output() и Почему терминал не запускается после запуска исполняемого файла Python? не отвечает на вопрос

1 Ответ

0 голосов
/ 16 декабря 2018

Короткая версия: check_output буферизует все выходные данные для возврата.Когда вы запускаете ls, его стандартный вывод идет в буфер check_output, а не в терминал.Когда вы выходите из оболочки, в которой вы находитесь в данный момент, вы получите все выходные сразу в виде одной строки Python.

Это приводит к вопросу, почему вы вместо этого получаете вспомогательную оболочку?выполнения содержимого cmd?Во-первых, вы используете bash неправильно;аргументом является файл для запуска, а не произвольная командная строка.Более правильной версией того, что вы делаете, будет

cmd = "printf  'xml files: %s\n' `find . -name '*.xml' | wc -l`"
subprocess.check_output(['/bin/bash', '-c', cmd])

или, если вы хотите, чтобы subprocess запустил для вас оболочку вместо явного ее выполнения,

subprocess.check_output(cmd, shell=True)

Объединение аргумента списка с shell=True почти никогда не является тем, что вам нужно.

Во-вторых, учитывая ваш исходный код, check_output сначала пытается объединить ваш список в одну строку, которая затем присоединяется к sh -c,То есть вы пытаетесь выполнить что-то вроде

sh -c /bin/bash "printf  'xml files: %s\n' `find . -name '*.xml' | wc -l`"

sh run /bin/bash, и ваша командная строка просто используется в качестве дополнительного аргумента для sh, который для целей этого вопросамы можем предположить, что игнорируется.Таким образом, вы находитесь в интерактивной оболочке, стандартный вывод которой буферизуется, а не отображается, как описано в первой части этого ответа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...