方法一:使用 subprocess.Popen()
参考:https://gist.github.com/gustavorv86/43e90e8059ceea9acb095c5118e781c5
可以在 shell 命令执行的过程中,一直接收输出。
def run_cmd(shellcmd, callback_fun, data=None):
proc = subprocess.Popen(shellcmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
line = ""
while True:
c = proc.stdout.read(1) # 每次读取一个字符
if c == b'\r' or c == b'\n': # 判断当前的字符,如果是回车(b'\r')或者(b'\n'),说明新的一行开始了
callback_fun(line, data) # 处理已经收集的一行
line = ""
continue
line = line + c.decode()
if b'' == c: # 如果读取到的字符为空,则说明管道结束了
break
if len(line) > 0: # 说明最后读了一些数据,只不过没有没有在最后读取到回车或者换行,但是也需要处理
callback_fun(line, data)
- 参数
shell=True
,如果没有这个参数,那么 shellcmd 就需要是类似exec
函数里面的列表一样,类似subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
。 - 参数
stdout=subprocess.PIPE
可以把子进程的stdout
输出到管道中。 - 参数
stderr=subprocess.STDOUT
会把子进程的错误输出,重定向到 stdout 中,类似2>&1
。
等待进程结束,然后获取所以的输入输出 p.communicate()
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
out, err = p.communicate()
return {'stdout': out, 'stderr': err, 'retcode': p.returncode}
方法二:使用 subprocess.run()
一次性获取所有的返回数据
import subprocess
command = "echo a; echo b"
ret = subprocess.run(command, capture_output=True, shell=True)
# before Python 3.7:
# ret = subprocess.run(command, stdout=subprocess.PIPE, shell=True)
print(ret.stdout.decode())