将“key:value”形式的字符串转换为列表或字典并提取值

时间:2016-02-18 06:32:20

标签: python linux

我需要使用linux命令

提取系统的空闲内存
cat /proc/meminfo

输出类似于:

MemTotal:        1979676 kB
MemFree:          396244 kB
Buffers:          265048 kB
Cached:           629892 kB
SwapCached:           60 kB
Active:           503916 kB
Inactive:         770644 kB
Active(anon):     116564 kB
Inactive(anon):   369112 kB
Active(file):     387352 kB
Inactive(file):   401532 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       2025468 kB
SwapFree:        2025276 kB
Dirty:               208 kB
Writeback:             0 kB
AnonPages:        379692 kB
Mapped:            76752 kB
Shmem:            106056 kB
Slab:             253328 kB
SReclaimable:     231816 kB
SUnreclaim:        21512 kB
KernelStack:        2720 kB
PageTables:        22152 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     3015304 kB
Committed_AS:    2489860 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      538576 kB
VmallocChunk:   34359176332 kB
HardwareCorrupted:     0 kB
AnonHugePages:    210944 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       38908 kB
DirectMap2M:     1988608 kB

现在,我只对前两行感兴趣,即参数MemTotal和MemFree。我编写了以下代码来提取前两个参数:

mi_l=[]
mt_l=[]
mf_l=[]
mf=[]
mi_j=[]
mi_mt=[]
mi_mf=[]
t=0
for i in range(0,4):
    tn1.write("cat /proc/meminfo")
    tn1.write("\n")
    time.sleep(2)
    rd_buf = telnet.read_very_eager()
    mi=rd_buf.splitlines()[:3]
    print "splitlines :\n"+str(mi)
    for ln in mi:
        mi_l.append([int(p) for p in ln.split() if p.isdigit()])
print(mi_l)
for i in range(0,12):
    print(mi_l[i])
for i in range(4,12):
    if i%3!=0:
        mt_l.append(mi_l[i])
        avail_mem=mt_l[0]
        print(mt_l)
for i in range(0,6):
    if i%2!=0:
        mf_l.append(mt_l[i])
        print(mf_l)
for i in mf_l:
    t=t+i
print(t)
ram_free=t/3
print "Total Available Memory : "+str(avail_mem)+"Free RAM :"+str(ram_free)

正如您所看到的,我正在尝试提取 MemFree 参数3次并获取这3个值的平均值。但是我收到错误'+'不支持的操作数类型:'int'和'list',这时我意识到 mf_l 原来是列表中的列表。 什么是获得我需要的最好方法?如果有人建议在代码或替代解决方案中进行调整,那将会很有帮助。

3 个答案:

答案 0 :(得分:2)

首先,您可以使用head -n 2 /proc/meminfo代替cat /proc/meminfo来获取/proc/meminfo中的前两行。

然后您可以从第二行提取数字并将其转移到如下数字:

import os

mem_free = 0
for i in range(4):
    tn1.write("head -n 2 /proc/meminfo")
    tn1.write("\n")
    time.sleep(2)
    rd_buf = telnet.read_very_eager()
    mi=rd_buf.splitlines()[:3]
    mem_free += int(mi[2].split()[1])

mem_free /= 4.0

答案 1 :(得分:1)

我已经解析了很多这种类型的文件。我做了一些更通用的东西,以便它适用于许多文件,所以我的例子会偏离你的。首先,您可以以不同方式处理telnet会话 - 让远程返回一个众所周知的字符串,告诉您命令何时完成。然后,只是拆分字符串而不是做复杂的,非显而易见的,容易出错的字符串索引。我使用dict以便我可以抓取我想要的任何数据,而不必担心数据出现的确切顺序。

info = { 'MemTotal': [0]*4, 'MemFree': [0]*4}

# it will look one way when echoed, another when executed
send_sentinel = '"********" "end sentinel" "********"'
check_sentinel = '******** end sentinel ****'

do_wait = False

for i in range(4):
    # wait between samples after first time through loop
    if do_wait:
        time.sleep(2)
    do_wait = True

    # in case crud is in pipe
    tn1.read_very_eager()
    # send command plus echo when done
    tn1.write('cat /proc/meminfo;echo {}\n'.format(send_sentinel))
    # wait for sentinel... i think the next read skips \r in return
    tn1.read_until(check_sentinel)
    txt = tn1.read_until('\n')

    want = 2 # for early break
    for line in txt.split():
        try:
            # assume we got a good line
            name, kb = line.split()[:2]
            name = name [:-1] # key rid of colon
            if name in info:
                info[name] = int(kb)
                want -= 1
                if not want:
                    break # early break
        except ValueError:
            pass # not our line

mem_free = sum(info['MemFree'])/4

print('total {}, free {}'.format(info['Memtotal'][0], mem_free))

答案 2 :(得分:1)

无需深入研究您的代码,您的专线     mi_l.append([int(p) for p in ln.split() if p.isdigit()]) 将列表(从列表推导语句中)附加到mi_l列表中。这就是你获得列表清单的原因。如果您想要一个单独的平面列表,您可以将“附加”改为“扩展” 这是您的代码的工作版本,大大简化了:
import time input_file = '35474429-in.txt' tn1 = open('35474429-out.txt', 'w') iterations = 3 mi_l=[] t = f = 0 for i in range(iterations): tn1.write("cat /proc/meminfo\n") time.sleep(2) rd_buf = open(input_file, 'r').read() #telnet.read_very_eager() mi=rd_buf.splitlines()[:2] # [:3] tn1.write("splitlines : %s\n" % str(mi)) for ln in mi: mi_l.extend([int(p) for p in ln.split() if p.isdigit()]) print(mi_l) for i in range(0, len(mi_l), 2): print(mi_l[i], mi_l[i+1]) t += mi_l[i] f += mi_l[i+1] ram_free = f / iterations ram_total = t / iterations results = "Average Available Memory : "+str(ram_total)+", Free RAM :"+str(ram_free) print(results) tn1.write(results)
您可以通过创建代码中指定的输入文件并使用示例输入的前两行填充代码来运行代码。它生成一个示例输出。一些事情适合你:
(1)当你需要多个地方的价值时,不要硬编码任何东西。制作和使用单个变量更好 (2)“append”将一个项添加到列表中。 “extend”将多个项添加到列表中 (3)range语句可以将第三个参数作为递增值 祝你好运。