2014-09-05 2 views
0
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 

о/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 

о/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'> 

Теперь моя проблема заключается в том, что я в состоянии получите output в виде списка, each из output на самом деле str. Я хочу проверить, находится ли Battery_Voltage в диапазоне от i.e более 20 В и аналогичен другим, например. Temperature и Inclination. Как мне извлечь значения для каждого, чтобы я мог выполнить их проверку? Также мне пришлось жестко запрограммировать его, чтобы обратиться к моему набору проверок, например.

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

Есть ли лучший способ сделать это?

ответ

0

Ну, когда вы получаете 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'> 

В вашем случае есть некоторые даты, которые вы не хотите конвертировать. Они поднимут ValueError, когда вы передадите их float.

Например:

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)) 

Если вы используете питона < 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

0

Существует и другой подход, который является более гибким и вы лучше контролировать условия, которые должны быть применены к этим значениям. Это может быть полезно, когда есть много полей для обработки, и вам нужно сделать некоторые более сложные вещи.

Мы можем динамически вызывать для каждого поля метод, специфичный для данного конкретного описания. Например, когда поле с описанием Батарея обрабатывается, мы вызываем process_battery класса FieldProcessor и так далее.

Таким образом, в вашей функции печати:

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 в float и т. Д.

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