2013-09-23 19 views
1

我的任務是通過snmp從打印機讀取錯誤代碼。幸運的是,我有一個可用的bash腳本來指導我完成這個神祕的任務。我正在寫一些python來從現有的腳本做一些不同的工作。現有的代碼似乎可以工作,但這很瘋狂,我希望用更多的python-y方法來解析比特。什麼是可讀/現代的解析基於位的錯誤代碼的方法?

首先,解釋我對當前代碼的閱讀。 hrPrinterDetectedErrorStatesnmpwalk查詢返回的錯誤代碼被編碼爲一個八位組串,通常帶有引號。所以引號與空格和換行符一起被刪除。錯誤代碼最多可以有四個字節,但如果爲零,通常會爲第二對發送空字節,因此在這種情況下會添加一對零。然後錯誤代碼被轉換爲十六進制。

現有的bash腳本:

parseErrorState() 
{ 
    setUpErrorCodes 
    # pull the error state w/o quotes 
    errorState=`snmpwalk -Oqvx -c public -v $snmpV $printerIP hrPrinterDetectedErrorState | grep -v "End of MIB" | tr -d '"'` 
    # remove spaces 
    errorCode=$(echo $errorState | tr -d [:space:]) 
    errorString="" 

    # if we don't have two hex bytes, append a byte of zeros 
    if [[ ${#errorCode} == 2 ]] 
    then 
    errorCode=$errorCode"00" 
    fi 

    # do hex conversion 
let errorCode=0x$errorCode 

if (($errorCode & $overduePreventMaint)) 
then 
    errorString=$errorString"Overdue Preventative Maintenance; " 
fi 
if (($errorCode & $inputTrayEmpty)) 
then 
    errorString=$errorString"Input Tray Empty; " 
fi 
if (($errorCode & $outputFull)) 
then 
    errorString=$errorString"Output Full; " 
fi 
if (($errorCode & $outputNearFull)) 
then 
... and about 12 more if-thens... 

該系列的IF-thens逐位比較errorCode與每個這些,並增加了相關的字符串輸出。

setUpErrorCodes() 
    { 
    lowPaper=32768 
    noPaper=16384 
    lowToner=8192 
    noToner=4096 
    doorOpen=2048 
    jammed=1024 
    offline=512 
    serviceRequested=256 

    inputTrayMissing=128 
    outputTrayMissing=64 
    markerSupplyMissing=32 
    outputNearFull=16 
    outputFull=8 
    inputTrayEmpty=4 
    overduePreventMaint=2 
    } 

我的Python版本使用subprocesssnmpwalk並執行格式化或多或少以上。然後:

# A dictionary of the errors and bit places 
errors = { 
    16: "low paper", 
    15: "no paper", 
    ...etc 

# a still very ugly bit parse starting with a hex str like '2A00': 
b = bin(int(hexstr, 16))[2:] # hex to int, int to bin, cut off the '0b' 
binstr = str(b) 
length = len(binstr) 
indices = [] 
for i, '1' in enumerate(binstr): 
    # find negative index of all '1's and multiply by -1 
    # a hack to get around the binary string not containing leading zeros 
    indices.append((i-length)*-1) 

然後,只需比較索引與錯誤字典,你就完成了。

無論如何,非常醜陋,可能相當低效。什麼是更高級的,可讀性更高的方法來實現相同的目標?

回答

2

既然你可以解析你的字符串,例如:

flags = int(hexstr, 16) 

認爲你正在尋找

flag_indices = [] 
for flag in errors: 
    if flags & (2**flag): 
     flag_indices.append(flag) 

而不是建立列表和索引,你可以直接做

(flags >> flag) & 1 

關於整數這將是一個該死的很多fas之三。

+0

這一個勝可讀性,所以給予好評那裏,但在指數運算效率失去了一些分VS斯文的答案。所以斯文一個鼻子。 – anthropomo

+0

我的更新如何? – Veedrac

+0

我通常不喜歡改變我的答案,但是這個新的答案是有效率的,並且對於十六進制字符串「8000」和更高的正確答案,Sven不會出於某種原因。 – anthropomo

3

你可以設置標誌的列表用一個簡單的循環:

errors = { 
    15: "low paper", 
    14: "no paper", 
    ... 
} 
flags = int(hexstr, 16) 
flag_indices = [] 
for i in range(max(errors)): 
    if flags & 1: 
     flag_indices.append(i) 
    flags >>= 1 
+0

This Works!原諒我的無知,'flags >> = 1'做了什麼? – anthropomo

+1

向右移位,所以相當於模2。 – Veedrac

+1

@Veedrac:相當於除以2,而不是2。 –