Python - 如何解析smartctl程序输出?

Pyr*_*erm 5 python parsing python-2.7

我正在 python 2.7.3 中为 smartctl 编写一个包装器...

我花了很长时间试图解决如何解析smartctlLinux 中程序的输出(具体来说是 Ubuntu x64)

我正在smartctl -l selftest /dev/sdx通过子进程运行并将输出抓取到变量中

该变量被分解为一个列表,然后我从输出中删除无用的标题数据和空行。

现在,我留下了一个字符串列表,这太棒了!

数据是表格形式的,我想将其解析为充满列表的 dict() (我认为这是通过阅读文档在 Python 中表示表格数据的正确方法)

以下是数据示例:

Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Short offline       Completed without error       00%     44796         -
# 2  Short offline       Completed without error       00%     44796         -
# 3  Short offline       Completed without error       00%     44796         -
# 4  Short offline       Completed without error       00%     44796         -
# 5  Short offline       Completed without error       00%     44796         -
# 6  Extended offline    Completed without error       00%     44771         -
# 7  Short offline       Completed without error       00%     44771         -
# 8  Short offline       Completed without error       00%     44741         -
# 9  Short offline       Completed without error       00%         1         -
#10  Short offline       Self-test routine in progress 70%     44813         -
Run Code Online (Sandbox Code Playgroud)

我可以看到尝试解析此问题的一些问题,并且愿意接受解决方案,但我也可能只是做错了;-):

  1. 状态文本Self-test routine in progress流过文本的第一个字符Remaining
  2. 列中Num,后面的数字与字符9之间没有#空格分隔

我在这里可能有点离谱,但这是我第一次尝试解析如此古怪的东西。

感谢所有愿意提前阅读这面文字墙的人!

到目前为止,这是我的代码,如果有人觉得有必要或发现它有用:

#testStatus.py

#This module provides an interface for retrieving
#test status and results for ongoing and completed
#drive tests

import subprocess

#this function takes a list of strings and removes
#strings which do not have pertinent information
def cleanOutput(data):

  cleanedOutput = []

  del data[0:3] #This deletes records 0-3 (lines 1-4) from the list

  for item in data:
    if item == '': #This removes blank items from remaining list
      pass
    else:
      cleanedOutput.append(item)

  return cleanedOutput


def resultsOutput(data):

  headerLines = []
  resultsLines = []
  resultsTable = {}

  for line in data:
    if "START OF READ" in line or "log structure revision" in line:
      headerLines.append(line)
    else:
      resultsLines.append(line)

  nameLine = resultsLines[0].split()
  print nameLine


def getStatus(sdxPath):
  try:
    output = subprocess.check_output(["smartctl", "-l", "selftest", sdxPath])

  except subprocess.CalledProcessError:
    print ("smartctl command failed...")

  except Exception as e:
    print (e)

  splitOutput = output.split('\n')

  cleanedOutput = cleanOutput(splitOutput)

  resultsOutput(cleanedOutput)


#For Testing
getStatus("/dev/sdb")
Run Code Online (Sandbox Code Playgroud)

Dav*_*sta 7

对于它的价值(这是一个老问题):smartctl有一个--json标志,您可以使用它,然后像普通 JSON 一样解析输出,因为版本 7.0

发行说明


mgk*_*bbs 1

主要的解析问题似乎是前三列;其余数据更直接。假设输出在字段之间使用空格(而不是制表符,这会更容易解析),我会进行固定长度解析,例如:

num = line[1:2]
desc = line[5:25]
status = line[25:54]
remain = line[54:58]
lifetime = line[60:68]
lba = line[77:99]
Run Code Online (Sandbox Code Playgroud)

标题行将以不同的方式处理。将数据放入什么结构取决于您想用它做什么。如果您主要想通过“num”标识符随机访问数据,则以“num”为键的字典可能是合适的。否则,列表可能会更好。每个条目(每行)可以是一个元组、一个列表、一个字典、一个类实例,或者可能是其他东西。如果您想按名称访问字段,那么每个条目一个字典或类实例可能比较合适。