I have original code like this below
if line[15:20] == 'Rx RF':
# decode RF message. format is:
# 02/13 23:54:28 Rx RF HouseUnit: B1 Func: On
line_list = line.split(' ')
house_code = line_list[5];
house_func = line_list[7]
return house_code, {'func': house_func}, 'button'
Like in description, if input "02/13 23:54:28 Rx RF HouseUnit: B1 Func: On"
this code will decode :
house_code = B1
house_func = On
Now I have 2 lines input :
02/13 23:54:28 Rx PL HouseUnit: A1
02/13 23:54:28 Rx PL House: A Func: On
I want to modify the code so that will have result :
house_code = A1
house_func = On
Anybody can help me?
I would suggest you to use regular expressions to parse such strings.
Try this:
import re
rf_full_pat = re.compile(r'^\s?(?P<date>\d\d/\d\d)\s+(?P<time>\d\d\:\d\d\:\d\d)\s+(?P<band1>[a-zA-Z]+)\s+(?P<band2>[a-zA-Z]+)\s+(?P<unittype>[a-zA-Z]+\:)\s+(?P<unit>\w+)\s+([a-zA-Z]+\:)\s+(?P<func>[a-zA-Z]+)\s?$')
rf_pat_pat = re.compile(r'^\s?(?P<date>\d\d/\d\d)\s+(?P<time>\d\d\:\d\d\:\d\d)\s+(?P<band1>[a-zA-Z]+)\s+(?P<band2>[a-zA-Z]+)\s+(?P<unittype>[a-zA-Z]+\:)\s+(?P<unit>\w+)\s?$')
test_full = "02/13 23:54:28 Rx RF HouseUnit: B1 Func: On"
test_pat = "02/13 23:54:28 Rx PL HouseUnit: A1"
def parse_rf(astring):
return rf_full_pat.match(astring) or rf_pat_pat.match(astring)
>>> print(parse_rf(test_full).groupdict())
Output:
{'func': 'On', 'band2': 'RF', 'unittype': 'HouseUnit:', 'band1': 'Rx', 'unit': 'B1', 'time': '23:54:28', 'date': '02/13'}
>>> print(parse_rf(test_pat).groupdict())
Output:
{'band2': 'PL', 'unittype': 'HouseUnit:', 'band1': 'Rx', 'unit': 'A1', 'time': '23:54:28', 'date': '02/13'}
Now, you can easily access named properties....
Thank you for your suggestion, however your code cannot be applied,
since input can be 1 line (original code) and can be 2 lines (need to modify code)
Please see below for original code
def parse_mochad_line(self, line):
"""
Parse a raw line of output from mochad
"""
# bail out unless it's an incoming RFSEC message
if line[15:23] == 'Rx RFSEC':
# decode message. format is either:
# 09/22 15:39:07 Rx RFSEC Addr: 21:26:80 Func: Contact_alert_min_DS10A
# ~ or ~
# 09/22 15:39:07 Rx RFSEC Addr: 0x80 Func: Motion_alert_SP554A
line_list = line.split(' ')
addr = line_list[5]
func = line_list[7]
func_dict = self.decode_func(func)
return addr, {'func': func_dict}, 'security'
elif line[15:20] == 'Rx RF':
# decode RF message. format is:
# 02/13 23:54:28 Rx RF HouseUnit: B1 Func: On
line_list = line.split(' ')
house_code = line_list[5];
house_func = line_list[7]
return house_code, {'func': house_func}, 'button'
return '', ''
so I want to extend the code so that can accept 2 lines, something like below.
I think I will need to save variable filtered from #1 line input and
call that variable while #2 line input being processed.
But I have no idea how to do this???
elif line[15:20] == 'Rx PL':
# decode RF message. input has 2 lines, format is:
# 02/13 23:54:28 Rx PL HouseUnit: A1
# 02/13 23:54:28 Rx PL House: A Func: On
line_list = line.split(' ')
if line[21:27] == 'HouseU': #filtering #1 line input for 'HouseUnit'=A1
house_code = line_list[5]
#but this variable 'house_code' has to be saved somewhere
#so that can be called when the next line input being processed
elif line[21:27] == 'House:': #filtering #2 line input for 'Func'=On
house_func = line_list[7]
house_code = ????
#here need to call variable 'HouseUnit'=A1 which already being saved
#while filtering #1 line input
If your function accepts input line by line, you may use function-level caching. I will show you how to use
mutable default value
to this end
Let's start by splitting the line unconditionally
def parse_mochad_line(self, line, _house_unit=[]):
elements = line.split()
classifier = ''.join(elements[2:4])
if classifier == 'RxRFSEC':
......
elif classifier == 'RxRF':
.....
elif classifier == 'RxPL':
if not house_unit:
_house_unit.append(...)
else:
......
_house_unit.clear()
Pay attention - you cannot assign
_house_unit
, because that will ruin caching mechanism