代码之家  ›  专栏  ›  技术社区  ›  user3313834

为什么我们在运行子进程后从终端中丢失stdout。检查输出(xyz,shell=true)?

  •  0
  • user3313834  · 技术社区  · 6 年前

    我有这条巴什线:

    $ 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? 不回答问题

    1 回复  |  直到 6 年前
        1
  •  1
  •   chepner    6 年前

    简短的版本是 check_output 正在缓冲所有要返回的输出。当你奔跑 ls ,其标准输出将 校验输出 的缓冲区,而不是终端。当您退出当前所在的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 几乎不是你想要的。

    其次,考虑到你的原始代码, 校验输出 首先尝试将列表组合成一个字符串,然后将该字符串连接到 sh -c . 也就是说,你试图执行

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

    sh /bin/bash ,您的命令字符串只是用作 就这个问题而言,我们可以假定它被忽略了。因此,您在一个交互shell中,它的标准输出是缓冲的,而不是显示的,如这个答案的第一部分所述。