使用子进程 popen 运行列表命令字符串并获取输出

Posted

技术标签:

【中文标题】使用子进程 popen 运行列表命令字符串并获取输出【英文标题】:Running a list command strings with subprocess popen and getting the output 【发布时间】:2018-11-05 19:25:02 【问题描述】:

我正在尝试在这样的 python 脚本中运行多个 UNIX 命令

import subprocess


cmds = ['sleep 3', 'uptime','time ls -l /']


p = subprocess.Popen(cmds,stdout=subprocess.PIPE,shell=True)


while p.poll() is None:
    time.sleep(0.5)


tempdata = p.stdout.read()



print(tempdata)

但是我的输出不包含所有输出并且似乎没有运行所有命令。设置 shell=False 也会导致错误。

Traceback (most recent call last):
  File "task1.py", line 32, in ?
    p = subprocess.Popen(commands,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=False)
  File "/usr/lib64/python36/subprocess.py", line 550, in __init__
    errread, errwrite)
  File "/usr/lib64/python36/subprocess.py", line 996, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

【问题讨论】:

【参考方案1】:

当您创建一个新进程时,您不会向它传递要运行的命令列表;相反,您将单个命令传递给它——作为字符串(使用shell=True)或作为参数列表(使用shell=False)。

import subprocess

cmds = ['sleep 1', 'uptime', 'ls -l /']

for cmd in cmds:
    stdout = subprocess.check_output(cmd, shell=True)
    print('\n# '.format(cmd))
    print(stdout)

如果您只是想收集标准输出,subprocess.check_output() 可能比Popen() 更简单——但任何一种方法都可以使用,具体取决于您需要对该过程执行的操作。

【讨论】:

【参考方案2】:

您的问题是“睡眠 3”导致您从回溯中得到的错误,当我删除它时它起作用了。

【讨论】:

【参考方案3】:

运行所有这些:

cmds = ['sleep 3', 'uptime','time ls -l /']

您必须为每个人调用 popen:

for cmd in cmds:
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

    while p.poll() is None:
        time.sleep(0.5)

    output = p.stdout.read()

或者更简单:

for cmd in cmds:
    output = subprocess.check_output(cmd, stdout=subprocess.PIPE, shell=True)

第二个问题:这会捕获所有写入标准输出的输出。要同时捕获 stderr,请将其重定向到 subprocess.PIPE

【讨论】:

以上是关于使用子进程 popen 运行列表命令字符串并获取输出的主要内容,如果未能解决你的问题,请参考以下文章

使用python子进程运行shell命令[重复]

使用python子进程运行shell命令[重复]

subprocess.Popen,从子进程(子)中获取变量[重复]

如何异步获取子进程'stdout数据?

如何使用子进程 Popen.communicate() 方法?

subprocess以及常用的封装函数