0

Is there a good way to handle non-existing dictionary keys?

I have a database based on dictionaries with keys that looks something like this

ID
   ver
      sub_ver
           A
           B
           C

I want to compare the values for the A, B, C-keys for each ID/ver/sub_ver to assure that:

 (A==B and C==None) or (A==C and B==None) or (A==B==C)

However not all "IDs" have A and B and C-keys/values

My not very nice code:

**loops outside of this for ID/ver/sub_ver** 
try:
    A = data_structure[ID][ver][sub_ver]['A']
    B = data_structure[ID][ver][sub_ver]['B']
    C = data_structure[ID][ver][sub_ver]['C']
except KeyError:
    try:
        A = data_structure[ID][ver][sub_ver]['A']
        B = data_structure[ID][ver][sub_ver]['B']
        C = None

    except KeyError: 
        try:
            A = data_structure[ID][ver][sub_ver]['A']
            B = None
            C = data_structure[ID][ver][sub_ver]['C']                    

Next i check if all values match

I use set() just in case the A/B/C-lists aren't in order

if not any((set(A)==set(B) and C==None, \
            set(A)==set(C) and B==None, \
            set(A)==set(B)==set(C))):
    set_of_problems.append([ID, ver, sub_ver, [A, B, C])

Is there a better way to do the nested try/except when it comes to non-existing keys in dictionaries?

user2987193
  • 133
  • 1
  • 1
  • 7
  • This may be of interest to you. http://stackoverflow.com/questions/3797957/python-easily-access-deeply-nested-dict-get-and-set – Cory Kramer Sep 26 '14 at 14:35

1 Answers1

5

You have too many try's; use dict.get() to get optional elements:

try:
    A = data_structure[ID][ver][sub_ver]['A']
except KeyError:
    # no A so error, next iteration of your loop
    continue

# we know ID, ver, and sub_ver all are present
B = data_structure[ID][ver][sub_ver].get('B')
C = data_structure[ID][ver][sub_ver].get('C')

if (C is None and A == B) or (B is None and A == C) or (A == B == C):
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Ahh .get() that works! In addition, in order to handle the values being lists i added default values to the get-functions .get('B', [None]) and changed C is None to C==[None] – user2987193 Sep 26 '14 at 14:58
  • 1
    @user2987193: that you need to use `set()` here is a separate issue really; it doesn't have an impact on the original problem and the solution for that problem. – Martijn Pieters Sep 26 '14 at 14:59