2012-12-17 99 views
2

我有一個子進程執行:Python迭代返回json的子流程?

lshw -json -C network 

如果我收到以下回:

{ 
    "id" : "network", 
    "class" : "network", 
    "claimed" : true, 
    "handle" : "PCI:0000:00:05.0", 
    "description" : "Ethernet interface", 
    "product" : "82545EM Gigabit Ethernet Controller (Copper)", 
    "vendor" : "Intel Corporation", 
    "physid" : "5", 
    "businfo" : "[email protected]:00:05.0", 
    "logicalname" : "eth0", 
    "version" : "00", 
    "serial" : "00:8c:42:77:58:49", 
    "units" : "bit/s", 
    "size" : 1000000000, 
    "capacity" : 1000000000, 
    "width" : 32, 
    "clock" : 66000000, 
    "configuration" : { 
     "autonegotiation" : "on", 
     "broadcast" : "yes", 
     "driver" : "e1000", 
     "driverversion" : "7.3.21-k8-NAPI", 
     "duplex" : "full", 
     "firmware" : "N/A", 
     "ip" : "10.211.55.10", 
     "latency" : "0", 
     "link" : "yes", 
     "multicast" : "yes", 
     "port" : "twisted pair", 
     "speed" : "1Gbit/s" 
    }, 
    "capabilities" : { 
     "msi" : "Message Signalled Interrupts", 
     "bus_master" : "bus mastering", 
     "cap_list" : "PCI capabilities listing", 
     "ethernet" : true, 
     "physical" : "Physical interface", 
     "logical" : "Logical interface", 
     "tp" : "twisted pair", 
     "10bt" : "10Mbit/s", 
     "10bt-fd" : "10Mbit/s (full duplex)", 
     "100bt" : "100Mbit/s", 
     "100bt-fd" : "100Mbit/s (full duplex)", 
     "1000bt-fd" : "1Gbit/s (full duplex)", 
     "autonegotiation" : "Auto-negotiation" 
    } 
    }, 

現在我還能在這個迭代,以確保我捕捉到所有的網絡接口(的情況下,有更多比一)這是不是我的系統的情況..此外,我怎麼可以從這個輸出中選擇1或2,我不需要整個數據。

我記住以下幾點:

def get_nic_data(): 
     lshw_cmd = "lshw -json -C network" 
     proc = subprocess.Popen(lshw_cmd, shell=True, stdout=subprocess.PIPE, 
                 stdin=subprocess.PIPE) 
     return proc.stdout 


def read_data(proc_output): 
     import simplejason as json 
     json_obj = json 

     json_obj.loads(proc_output) 

     #Obtain Vendor,Description,Product 
     #... 
     #... 

     json_obj.dumps(obtained_data_here) 

     #Not sure if this would work this way. 


    read_data(get_nic_data()) 

回答

6

不幸的是,你不能用-json輸出相結合-C級過濾;即使在最新版本中,JSON輸出也被嚴重破壞。相反,請自行篩選完整的 JSON輸出。請注意,在使用subprocess時,應避免使用shell=True,而應該在列表中傳遞;不需要管stdin,但是捕獲(沉默)stderr。

然後我們就可以遞歸在「孩子」的結構,挑選出任何有匹配的'class'鍵:

def get_nic_data(): 
    lshw_cmd = ['lshw', '-json'] 
    proc = subprocess.Popen(lshw_cmd, stdout=subprocess.PIPE, 
             stderr=subprocess.PIPE) 
    return proc.communicate()[0] 

def find_class(data, class_): 
    for entry in data.get('children', []): 
     if entry.get('class') == class_: 
      yield entry 

     for child in find_class(entry, class_): 
      yield child 

def read_data(proc_output, class_='network'): 
    import json 

    for entry in find_class(json.loads(proc_output), class_): 
     yield entry['vendor'], entry['description'], entry['product'] 

然後遍歷read_data(get_nic_data())

for vendor, description, product in read_data(get_nic_data()): 
    print vendor, description, product 
+0

除了'lshw -json'沒有返回一個有效的json文本(至少在我的機器上)。 – jfs

+0

'lshw -json'在同一個類的幾個結果的情況下不會返回一個有效的JSON,好像它應該是一個數組但是缺少'['和']'' – Raber

+0

@JFSebastian:Bugger,我希望那是OP的錯誤。我最近沒有發佈'lshw'版本(這裏是我的服務器上的Debian Squeeze)。缺少什麼,'['和']'括號? –

0

如果有多個網卡lshw不會返回有效的json文本。

import json 
import re 
from subprocess import STDOUT, check_output as qx 

# get command output 
output = qx("lshw -json -C network".split(), stderr=STDOUT) 

# get json parts 
_, sep, json_parts = output.rpartition(b"\r") 
if not sep: # no \r in the output 
    json_parts = output 

# convert it to valid json list 
jbytes = b"[" + re.sub(b"}(*){", b"}, {", json_parts) + b"]" 
L = json.loads(jbytes.decode()) 

# pretty print 
import sys 
json.dump(L, sys.stdout, indent=4) 

一個清潔的解決方案是使用lshw -xml產生可能由包裹很容易地轉化爲良好的XML輸出:它可以由輸出之後加入[/] /前和在對象之間添加,被固定它在根元素中:'<root>' +輸出+ '</root>'

+0

我得到的錯誤 - ValueError:沒有JSON對象可以解碼 – Dayan

+0

@Dayan:我測試了它,它在我的機器上工作。該解決方案對於lshw輸出中的更改很脆弱,因此應該在@Martijn中刪除'-C'選項以獲得有效的json。 – jfs