在Linux上,命令ps aux输出每个统计数据包含多列的进程列表。 e.g。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
...
postfix 22611 0.0 0.2 54136 2544 ? S 15:26 0:00 pickup -l -t fifo -u
apache 22920 0.0 1.5 198340 16588 ? S 09:58 0:05 /usr/sbin/httpd
我希望能够在使用Python时读取它,然后拆分每一行,然后拆分每一列,以便它们可以用作值。
在大多数情况下,这不是问题:
ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
processes = ps.split('\n')
我现在可以遍历进程以获取每一行并将其拆分为空格,例如
sep = re.compile('[\s]+')
for row in processes:
print sep.split(row)
然而,问题是最后一列,即命令,有时会有空格。在上面的例子中,这可以在命令中看到
pickup -l -t fifo -u
将被拆分为
['postfix', '22611', '0.0', '0.2', '54136', '2544', '?', 'S', '15:26', '0:00', 'pickup', '-l', '-t', 'fifo', '-u']
但我真的想要它:
['postfix', '22611', '0.0', '0.2', '54136', '2544', '?', 'S', '15:26', '0:00', 'pickup -l -t fifo -u']
所以我的问题是,如何拆分列,但是当涉及到命令列时,将整个字符串保留为一个列表元素而不是按空格拆分?
答案 0 :(得分:22)
使用第二个参数split
,它指定要将字符串拆分为的最大字段数。我猜你可以通过计算第一行中的字段数来找到该数字,即列标题。
ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
processes = ps.split('\n')
# this specifies the number of splits, so the splitted lines
# will have (nfields+1) elements
nfields = len(processes[0].split()) - 1
for row in processes[1:]:
print row.split(None, nfields)
答案 1 :(得分:13)
查看python.psutils包。
psutil.process_iter
返回一个生成器,您可以使用它来迭代所有进程。
p.cmdline
是每个Process对象的cmdline参数的列表,以您希望的方式分隔。
您只需一行就可以创建一个pids与(pid,cmdline,path)
的字典,然后无论如何都可以使用它。
pid_dict = dict([(p.pid, dict([('pid',p.pid), ('cmdline',p.cmdline), ('path',p.path)]))
for p in psutil.process_iter()]))
答案 2 :(得分:4)
为什么不使用PSI? PSI提供有关Linux和其他Unix变体的过程信息。
import psi.process
for p in psi.process.ProcessTable().values(): …
答案 3 :(得分:1)
maxsplit
方法的split
可选参数可能会对您有所帮助:
sep.split.(row, maxsplit=42)
答案 4 :(得分:1)
这是一个很好的例程和用法,可以帮助您:
def getProcessData():
ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
processes = ps.split('\n')
# this specifies the number of splits, so the splitted lines
# will have (nfields+1) elements
nfields = len(processes[0].split()) - 1
retval = []
for row in processes[1:]:
retval.append(row.split(None, nfields))
return retval
wantpid = int(contents[0])
pstats = getProcessData()
for ps in pstats:
if (not len(ps) >= 1): continue
if (int(ps[1]) == wantpid):
print "process data:"
print "USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND"
print "%-10.10s %10.10s %10.10s %10.10s %10.10s %10.10s %10.10s %10.10s %10.10s %s" % (ps[0], ps[1], ps[2], ps[3], ps[4], ps[5], ps[6], ps[7], ps[8], ps[9])