从Python逐行读取shell输出

3
我需要从Python脚本中读取shell命令的输出,并将每行填入列表中:
问题: 如果我将命令输出保存为变量,循环周期会逐个字符地读取它。
#!/usr/bin/python
import subprocess

CMD = "ls -la"
output = subprocess.check_output(CMD, shell=True)
list = []
for line in output:
    list.append(line)
print list

错误输出: ['t', 'o', 't', 'a', 'l', ' ', '5',...]

解决方法: 作为一种解决方法,我将命令输出重定向到文件中,然后逐行读取:

#!/usr/bin/python
import subprocess

CMD = "ls -la > tmp"
subprocess.call(CMD, shell=True)
list = []
f = open("tmp", "r")
for line in f:
    list.append(line)
print list

良好的输出 ['总共52个\n','drwxrwxr-x 3 ajn ajn 4096 mars 11 17:52 .\n',...]

问题: 如何将第二种方法的结果与第一种方法(无文件操作,全部在程序内部)结合使用?

4个回答

12

我不是专业的Python开发者,但这段代码应该适用于你,而且看起来更加清晰易懂:

import subprocess
cmd = ["ls", "-la"]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
for line in proc.stdout.readlines():
    print line

4

不要使用proc.stdout.readlines()。它会在返回结果之前读取所有的输出。你需要使用proc.stdout

这里是yy.py

import subprocess
cmd = ["bash", "./yy.sh"]

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
for line in proc.stdout:
    print( line )

这里是 yy.sh 文件:

for a in 1 2 3 4 5 6 7 8 9 0; do
    echo "hi $a !!!"
    sleep 1
done

运行yy.py会逐行输出结果。

如果你使用proc.stdout.readlines(),你需要等待10秒钟才能获取所有的输出。


超级棒的答案!我也会使用 line.decode('UTF-8') 将字节序列转换为字符串。 - Abdul Munim

2
你尝试过使用join吗?并且在换行符(\n)上使用split
#!/usr/bin/python
import subprocess

CMD = "ls -la"
output = subprocess.check_output(CMD, shell=True)
lst = []
for char in output:
    lst.append(char)
print ''.join(lst).split('\n')

基本上将所有的输出连接成一个字符串,然后按换行符拆分,创建一个单独输出的列表。同时,将变量命名为list是不好的实践,因为在Python中这是一种类型。尝试使用lstlist1代替。

你也可以将其简化为:

#!/usr/bin/python
import subprocess

CMD = "ls -la"
output = subprocess.check_output(CMD, shell=True)
print output.split('\n')

作为subprocess.check_output()的返回值是一个字符串,所以不需要循环遍历每个字符,只需使用split在字符串上获取输出列表即可。

1

@glenn-jackman 和 @tui-popenoe 的回答都可以:

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
for line in proc.stdout.readlines():
    print line

output = subprocess.check_output(CMD, shell=True)
print output.split('\n')

但是,我使用了 subprocess.Popen,因为它对于管道很有用:

p1 = subprocess.Popen(['ip','-la'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['grep','afile'], stdin=p1.stdout,stdout=subprocess.PIPE)
p3 = subprocess.Popen(['awk','{ print $6; }'], stdin=p2.stdout,stdout=subprocess.PIPE)

output = p3.communicate()[0]

for ln in output.split('\n'):
    print ln

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接