I am new to python and am trying to learn nested dictionary's but I think I am mixing some standards. So first i am not sure i am using the proper terminology so feel free to correct. I "think" what I am doing is having a key relate to a list as so...
errorlist = {
key1 : ["error1", "error2"]
key2 : ["error3", "error4"]
}
when i setup up like that i can change any aspect of what is there but i have not figured out how to add things later for example
errorlist = {
key1 : ["error1", "error2", "error5", "error6"]
key2 : ["error3", "error4"]
}
the goal is to have several devices with a list of what errors they may have active at any given time and the list is updated as more errors show. Is this a good format or would another structure be better? I have tried looking around but everything is key:value so that makes me think I might not be using dictionary correctly.
I have narrowed it a little. If I do
errorlist["key1"].append("error5")
it works but if i do
key_val = "key1"
errorlist[key_val].append("error5")
it barfs. so my update in theory works it is my reference value that is failing.
You're going to need to show the code (a minimal, complete working example), plus the full traceback of the error. From the last post, the two lines look equivalent.
Also, this:
errorlist = {
key1 : ["error1", "error2"]
key2 : ["error3", "error4"]
}
would raise NameError if key1 is not defined before that. Or you want key1 and key2 in quotes.
Problem as described has little to do with dictionaries. Strings are immutable and don't have .append() method:
>>> s = 'abc'
>>> s.append('d')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'append'
Regarding dictionaries: just an idea:
>>> keys = 'first', 'second', 'third'
>>> d = dict()
>>> for i, key in enumerate(keys):
... d.setdefault(key, []).append(i)
...
>>> d
{'first': [0], 'second': [1], 'third': [2]}
Thanks for the info. I had not posted what code I had because it was a mess of attempts at learning dictionary. After some coffee and RTFM I got this working. So now it is a issue of expanding it for other units and seeing if the code is clean enough.
#!/usr/bin/python3
import sys
import os
import subprocess
class ErrorFind():
def __init__(self):
self.APC_Error_List = {
"0x3408":"Internal power supply #1 fault.",
"0x340A":"Internal power supply #2 fault.",
"0x3414":"Device overload.",
"0x341A":"Phase overload.",
"0x3420":"Bank overload.",
"0x3426":"Outlet overload.",
"0x3410":"Device low load.",
"0x3412":"Device near overload.",
"0x3416":"Phase low load.",
"0x3418":"Phase near overload.",
"0x341C":"Bank low load.",
"0x341E":"Bank near overload.",
"0x3422":"Outlet low load.",
"0x3424":"Outlet near overload."
}
self.ServerTech_Error_List = []
self.Error_Results = {}
self.grep_search_holder = "Holds grep result while looping through error codes"
#Uses grep to search syslog dir /var/log/pdu/ for the error in the error list. Then the readable version is used to call a sorting method
def Search_Code(self):
for code in self.APC_Error_List:
self.grep_search_holder = str(subprocess.check_output(["grep -r " + code + " /var/log/pdu/ | sed '/rsyslog/d' | awk '{print $2}' | sort -u "], shell=True).decode('utf-8'))
Code2Text = self.APC_Error_List.get(code)
self.Sort_Code(Code2Text)
#This takes the string of IPs and removes one at a time as it is proccessed into the dictionary. The IP is changed to DNS name as it is stored.
#If the PDU already has a entry the saved info is appeneded to the new addtional info.
def Sort_Code(self, codepass):
count = self.grep_search_holder.count("\n")
for segment in range(count):
NextIP = (self.grep_search_holder.find('\n'))
ActiveIP = (self.grep_search_holder[0: NextIP])
ActiveIP = str(ActiveIP.strip())
ActiveIP2Name = str(subprocess.check_output(["nslookup " + ActiveIP + " | grep name | awk '{print $4}'"], shell=True).decode('utf-8')).strip(".\n")
self.grep_search_holder = self.grep_search_holder[NextIP+1:]
if ActiveIP2Name not in self.Error_Results:
self.Error_Results[ActiveIP2Name] = codepass
else:
CurrentData = self.Error_Results.get(ActiveIP2Name)
UpdatedData = (CurrentData + ", " + codepass)
self.Error_Results[ActiveIP2Name] = UpdatedData
def Save_Data(self):
for key in self.Error_Results:
Print_Error = open('error.txt', 'at')
Print_Error.write(key + " " + self.Error_Results.get(key))
Print_Error.write ("\n")
Print_Error.close()
# ------------------------- end of class -------------------------------------
# ------------------------- main --------------------------------------------
error_obj=ErrorFind()
error_obj.Search_Code()
error_obj.Save_Data()
[root@rsyslog ~/scripts ]#
output sample
pdu-dur3-92ag-2.datadomain.com Internal power supply #2 fault.
pdu-dur-12f-1.datadomain.com Internal power supply #2 fault.
pdu-dur-122m-2.datadomain.com Device overload., Phase overload., Device near overload., Phase near overload.
pdu-dur-22ao-1.datadomain.com Device overload., Phase overload., Bank overload., Device near overload., Phase near overload., Bank near overload.
pdu-dur-96af-1.datadomain.com Device overload., Phase overload., Bank overload., Device near overload., Phase near overload., Bank near overload.
pdu-dur-36j-1.datadomain.com Device overload., Phase overload., Bank overload., Device near overload., Phase near overload., Bank near overload.
pdu-dur-86d-1.datadomain.com Device overload., Phase overload., Bank overload., Device near overload., Phase near overload., Bank near overload.