【问题标题】:Why do we lost stdout from a terminal after running subprocess.check_output(xyz, shell=True)?为什么我们在运行 subprocess.check_output(xyz, shell=True) 后会从终端丢失标准输出?
【发布时间】:2023-03-24 12:48:01
【问题描述】:

我有这个 bash 行:

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

当我以这种方式从 python 运行它时 python 解释器停止 并且我的终端 不再有标准输出::

$ 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

>>> 

以下两个问题No output from subprocess.check_output()Why is terminal blank after running python executable?不回答问题

【问题讨论】:

  • 试过原始输出? cmd = r"printf 'xml files: ...\n"。因为这个\n char 可能会阻塞shell
  • 为什么是['/bin/bash', cmd] 而不是['/bin/bash', '-c', cmd]bash 期望它的参数是一个文件。 -c 选项使其从参数中读取脚本。
  • 为什么要 bash?这可以使用带有过滤器的os.walk 的纯python 来完成,然后打开文件并在行列表中使用len...
  • 另外,在有效的命令中,您根本没有使用 bash 前缀。这两个是不等价的。
  • 谢谢Jean-François,但问题不是 - 两个 cmd 是否等效,如何使 subprocess.check_output 行工作,但如何解释 1. python 退出到终端的事实2.终端没有插入任何标准输出

标签: python bash subprocess


【解决方案1】:

简短的版本是check_output 正在缓冲所有输出以返回。当您运行ls 时,它的标准输出将发送到check_output 的缓冲区,而不是终端。当您退出当前所在的 shell 时,您会立即将所有输出作为单个 Python 字符串获取。

这就引出了一个问题,为什么你首先得到一个子shell,而不是执行cmd的内容?首先,您使用bash 错误;它的参数是要运行的文件,而不是任意的命令行。你正在做的更正确的版本是

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 的附加参数,就本问题而言,我们可以假设它被忽略。因此,您处于一个交互式 shell 中,其标准输出被缓冲而不是显示,如本答案的第一部分所述。

【讨论】:

    猜你喜欢
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    相关资源
    最近更新 更多