我有这条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
$
显然,这里的问题不是如何使python的bash起作用:
>>> 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
>>>
以下两个问题No output from subprocess.check_output()和Why is terminal blank after running python executable?无法回答问题
答案 0 :(得分:1)
简短的版本是check_output
正在缓冲所有输出以返回。运行ls
时,其标准输出将到达check_output
的缓冲区,而不是终端。退出当前所在的外壳程序后,您将作为单个Python字符串一次获得所有输出。
这导致了一个问题,为什么首先要获得一个子shell,而不是执行cmd
的内容?首先,您使用bash
错误;它的参数是要运行的 file ,而不是任意命令行。您正在做的事情的更正确版本是
cmd = "printf 'xml files: %s\n' `find . -name '*.xml' | wc -l`"
subprocess.check_output(['/bin/bash', '-c', cmd])
或者,如果您希望subprocess
为您运行一个shell,而不是显式执行它,
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
运行/bin/bash
,并且您的命令字符串仅用作sh
的附加参数,出于这个问题的目的,我们可以假定它被忽略了。因此,您处于交互式外壳中,如本答案第一部分所述,该外壳的标准输出被缓冲而不是显示。