1

I want to run a line of code if any of the exceptions are met, but not if the try succeeds, a bit like the opposite of else when using try/except.

Currently I have exceptionOccured to set to True if an exception occurs, but I'm guessing there should be a more pythonic way of doing this.

Here's the current code I have, it was an attempt to edit values in a dictionary from a list, and create the keys if they don't exist. How would I redo the exceptions so that exceptionOccured is not needed?

dictionaryValue = {"data": dict.fromkeys( [0, 1, 2, 3] ), "data2": {0: "test",1:"test2"}}

reducedDictionary = dictionaryValue
valueList = ["data", 1, 64, "Testing", "value"]
canOverwriteKeys = True
for i in valueList[:-2]:
    exceptionOccured = False
    try:
        if type( reducedDictionary ) != dict:
            raise ValueError()
        elif reducedDictionary.get( i, False ) == False:
            raise KeyError()
    except ValueError:
        print "not dictionary"
        reducedDictionary = {}
        exceptionOccured = True
    except KeyError:
        print "key doesn't exist"
        exceptionOccured = True
    if exceptionOccured or ( type( reducedDictionary[i] ) != dict and canOverwriteKeys ):
        print "setting key value"
        reducedDictionary[i] = {}
    reducedDictionary = reducedDictionary[i]
reducedDictionary[valueList[-2]] = valueList[-1]
print dictionaryValue

Edit: Improved the code based on the answers, thanks :)

def editDictionary( dictionaryName, listOfValues, canOverwriteKeys=True ):
    reducedDictionary = dictionaryName
    for i in valueList[:-2]:
        if type( reducedDictionary ) != dict:
            reducedDictionary = {}
        try:
            if reducedDictionary.get( i, False ) == False:
                raise ValueError()
            elif type( reducedDictionary[i] ) != dict:
                if not canOverwriteKeys:
                    return
                raise KeyError()
        except( ValueError, KeyError ):
            reducedDictionary[i] = {}
        except:
            print "Something went wrong"
            return
        reducedDictionary = reducedDictionary[i]
    reducedDictionary[valueList[-2]] = valueList[-1]
2
  • In addition to (@Martijn) you would probably want to add the exception check in finally clause. Because the code might throw an exception, which if it is not handled by your except, your last check (if condition) will not be executed. Commented Mar 10, 2015 at 15:31
  • Yeah I usually don't bother with catching the different exceptions, so when doing it this time I wasn't sure if people used the final except, or ignored it so they could see any errors :) Commented Mar 10, 2015 at 15:47

2 Answers 2

2

Just catch both exceptions in one handler:

try:
    # ...
except (ValueError, KeyError) as e:
    if isinstance(e, ValueError):
        print "not dictionary"
        reducedDictionary = {}
    else:
        print "key doesn't exist"
    print "setting key value"
    reducedDictionary[i] = {}

If your exception handlers are more complex, you could also use a function:

def handle_common_things():
    # things common to all exception handlers

try:
    # ...
except Exception1:
    # do exception-specific things
    handle_common_things()
except Exception2:
    # do exception-specific things
    handle_common_things()
Sign up to request clarification or add additional context in comments.

3 Comments

Ah thanks a lot, works great. To get around the part where it also checks the dictionary[i] is also a dictionary and that overwrite keys is enabled, I put it with the KeyError part in the try statement, is that probably how you'd do it? Also I'll keep the 2nd part of the question in mind if I do have a more complicated one in the future, for most of the time though I just use except by itself :)
@Peter: You'd not get a key error if dictionary[i] exists but is the wrong value. :-)
I know, but I only need something different from the value error aha, the value error will set the value to an empty dictionary before running the main except code, whereas key error will just skip to the main except code ;p
1

I'd probably go with Martijn's answer, but you can also wrap your try/except block in another layer of try/except (and in real code I'd frown on using a bare except like this, or more likely define a new exception that's thrown from inside any except: clauses that you want to detect)

def exception_test(val):
   try:
      try:
         result = 1.0 / val
      except ZeroDivisionError:
         print "Divide by zero"
         raise
      else:
         print "1 / {0} = {1}".format(val, result)
   except:
      print "there was an exception thrown."


>>> exception_test(2.0)
1 / 2.0 = 0.5
>>> exception_test(0)
Divide by zero
there was an exception thrown.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.