获取打印在列表的形式,并访问每个那些

问题描述:

from myfolder import typing_commands as tcm 
import sys, StringIO 
class InfoTest(StartUpTest): 
    IS_TEST = True 
    def __init__(self): 
     super(InfoTest, self).__init__() 

    def setup(self): 
     return 

    def runtest(self): 
     tcm.erase_flash() 
     self.boot() # boot method is defined in StartUpTest class 
     time.sleep(20) 
     tcm.info_read() #Here it prints all the info see o/p1 

     #To get The printed data in list form 
     old_stdout = sys.stdout 
     capturer = StringIO.StringIO() 
     sys.stdout = capturer 
     tcm.info_read() 
     sys.stdout = old_stdout 
     output = capturer.getvalue().splitlines() 

     for each in output[8:]: 
      print each, type(each) 
     print type(output) #see o/p2 
     return 

O/P1的:获取打印在列表的形式,并访问每个那些

Info as desired: 
Downloading Logs... 
Info Downloaded! 

#################### 
Info Entry 1: 
#################### 
     Type    : Survey 
     Survey_time   : 2014-09-05 10:10:40 
     Inclination (deg): 45 
     Temperature  (C) : 30.00 
     Battery_Voltage (mV): 24.0 

O/P2:

 Survey_time   : 2014-09-05 10:11:44 <type 'str'> 
     Inclination (deg): 45 <type 'str'> 
     Temperature  (C) : 30.00 <type 'str'> 
     Battery_Voltage (mV): 24.0 <type 'str'> 

<type 'list'> 

现在我的问题是,虽然我能以列表形式获得outputoutputeach实际上是str。我想检查Battery_Voltage是否在大于20V的范围内,并且像其他人一样。 TemperatureInclination。我应该如何提取每个的值,以便我可以对它们执行检查?另外,我必须对它进行硬编码才能接触到我的一系列检查,例如。

for each in output[8:]: 
      print each, type(each) 

有没有更好的方法来做到这一点?

那么,当你获得output你这样做:

output = capturer.getvalue().splitlines() 

现在......在这里,你永远StringIO的内容(这是str英格斯)转换为其他类型。 output列表中的元素都是字符串,即使是您感兴趣的(output[8:])也是some name: number形式的字符串,所以python不可能神奇地了解您对号码部分感兴趣并自动为您转换这些值。

您希望显式转换这些字符串中表示的数字。

将字符串转换为数字,你可以简单地调用float(或int为整数):

>>> float('1.0') 
1.0 
>>> type(float('1.0')) 
<class 'float'> 

你的情况有一些日期,你不想转换。当你将它们传递给float时,这些将会产生ValueError

例如:

import contextlib 

capturer = StringIO.StringIO() 
with contextlib.redirect_stdout(capturer): 
    tcm.info_read() 
output = capturer.getvalue().splitlines() 

for line in output[8:]: 
    name, value = line.split(':') 
    try: 
     value = float(value) 
    except ValueError: 
     # this is a date. Keep it as a string or do something else. 
     pass 
    print(name, ':', value, type(value)) 

如果您正在使用python < 3。4,而不是contextlib.redirect_stdout可以使用sys.__stdout__恢复旧值:

sys.stdout = StringIO.StringIO() 
tcm.info_read() 
output = sys.stdout.getvalue().splitlines() 
sys.stdout = sys.__stdout__ 

一旦你转换你的价值观,你可以做你想要与他们的检查(这可能将取决于name部分)


正如我的建议:我想从这些数据建立一个dict,这样就可以很容易地通过名称来访问不同的值:

data = {} 
for line in output[8:]: 
    name, value = line.split(':') 
    try: 
     value = float(value) 
    except ValueError: 
     # this is a date. Keep it as a string or do something else. 
     pass 
    data[name.strip().split()[0].lower()] = value 

之后,你可以这样做:

if data['temperature'] > 50: 
    print('Temperature above 50 C') 
elif data['battery_voltage'] < 20: 
    print('Voltage too low') 
+0

谢谢吨..完美的作品! – tryPy 2014-09-05 19:08:28

还有另一种方法是更加灵活和你有过哪些必须适用于那些值的条件更好的控制。当有很多字段需要处理时,这可能会有帮助,并且您需要做一些更复杂的工作。

我们可能会动态地为每个字段调用特定于此特定说明的方法。例如,当正在处理描述电池的字段时,我们呼叫process_battery类别字段处理器依此类推。

所以在您的打印功能:

for each in output[8:]: 
      print each, type(each) 

我想补充一些像这样的代码:

import re, sys 
from collections import namedtuple 

for each in output[8:]: 

    # I prefer using namedtuple so we can use tuple.description and tuple.value 
    field = namedtuple("field", "description value") 

    # Regular expression for extracting the description and value 
    # May be optimized, play with it :) takes description containing A-Z,a-z,_ 
    result = re.findall(r'^ *([A-Za-z_]*).*: (.*)$', each) 
    if len(result): 

     # Make namedtuple from tuple 
     field = field._make(result[0]) 

     processor = FieldProcessor() 

     # Get function of FieldProcessor with description name 
     process_func = getattr(processor, 'process_'+field.description.lower(), None) 

     if callable(process_func): 
      process_func(field) 

    else: 
     print "Cannot parse field "+each 

然后我们就可以有FieldProcessor类,在那里你可以做你的价值观什么。我期待有没有转换str浮动等问题。

class FieldProcessor: 
    def process_voltage(self, field): 
     pass 

    def process_inclination(self, field): 
     # Converting to float, int, ... 
     if field.value > 20: 
      print "Inclination more then 20" 

    def process_survey_time(self, field): 
     pass 

    def process_temperature(self, field): 
     pass