python 中的调用子进程 "ls -l folder | wc -l" 无法完成

Call subprocess "ls -l folder | wc -l" in python can't be done

我想运行这个命令使用调用子进程

ls -l folder | wc -l

我在 Python 文件中的代码在这里:

subprocess.call(["ls","-l","folder","|","wc","-l"])

我收到这样的错误消息:

ls: cannot access |: No such file or directory
ls: cannot access wc: No such file or directory

好像命令|wc不能被call subprocess读取。

我该如何解决?

尝试使用字符串作为第一个参数的 shell 选项:

subprocess.call("ls -l folder | wc -l",shell=True)

虽然这项工作有效,但请注意,不建议使用 shell=True,因为它可能会通过 shell injection 引入安全问题。

您需要自己实现管道逻辑才能使其正常工作。

def piped_call(prog1, prog2):
  out, err = subprocess.call(prog1).communicate()
  if err:
    print(err)
    return None
  else:
    return subprocess.call(prog2).communicate(out)

假设您想避免使用 subprocess.call(..., shell=True),您可以尝试使用 subprocess.PIPE。

import subprocess

# Run 'ls', sending output to a PIPE (shell equiv.: ls -l | ... )
ls = subprocess.Popen('ls -l folder'.split(),
                      stdout=subprocess.PIPE)

# Read output from 'ls' as input to 'wc' (shell equiv.: ... | wc -l)
wc = subprocess.Popen('wc -l'.split(), 
                      stdin=ls.stdout, 
                      stdout=subprocess.PIPE)

# Trap stdout and stderr from 'wc'
out, err = wc.communicate()

if err:
    print(err.strip())

if out:
    print(out.strip())

For Python 3 请记住这里使用的 communicate() 方法将 return 一个 byte 对象而不是一个字符串。 :

在这种情况下,您需要使用 decode():

将输出转换为字符串
if err:
    print(err.strip().decode())
if out:
    print(out.strip().decode())

您可以通过将一个进程的 stdout 与另一个进程的 stdin 连接来设置命令管道。在您的示例中,错误和最终输出被写入屏幕,因此我没有尝试重定向它们。这通常比 communicate 这样的东西更可取,因为它们 运行 是并行的,而不是等待一个程序完成后再开始另一个程序(并鼓励将数据移动到父级中的费用)。

import subprocess

p1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["wc","-l"], stdin=p1.stdout)
# close pipe in parent, its still open in children
p1.stdout.close()
p2.wait()
p1.wait()