0

I am catching two exceptions in Python in such way:

#ex1
try: 
    #some code
except:
    #some code to e.g. print str

#ex2
try: 
    #some code
except: 
    #some code to e.g. print str or exit from the program.

if ex1 raises an exception then I want to skip ex2. if ex1 does not raise an exception the I want to try ex2.

What is the most elegant way to code it?

My current approach is to wrap it in a function block as below and use return in right place:

def myExceptions(someArgs):
    #ex1
    try: 
        #some code
    except:
        #some code
        return

    #ex2
    try: 
        #some code
    except: 
        #some code

and then I just call the function in right place myExceptions(someArgs)

  • You can have multiple `except:` clauses for different exceptions for the same try block, there's no need for all these shenanigans. See https://docs.python.org/3/tutorial/errors.html – pvg May 02 '17 at 22:30
  • Possible duplicate of [Catch multiple exceptions in one line (except block)](http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block) – TemporalWolf May 02 '17 at 22:34
  • Also, ["using a bare `except:` is almost never a good idea"](https://docs.python.org/2/howto/doanddont.html#except). – TemporalWolf May 02 '17 at 22:36
  • Both try blocks do not have the same code hence why two separate try block with once excepction each. –  May 02 '17 at 22:42
  • I feel like his question includes the answer to your question as an example. – TemporalWolf May 02 '17 at 22:44
  • The example on the link 'Catch ....' is different from my question. –  May 02 '17 at 22:44

3 Answers3

2

EDIT: This will work as you described:

try:
    msg = make_msg_fancy(msg)
    msg = check_for_spam(msg)
except MessageNotFancyException:
    print("couldn't make it fancy :(")
except MessageFullOfSpamException:
    print("too much spam :(")

When an exception occurs, it skips the rest of the try block and continues at the exception... it doesn't go back.


You are doing something like this:

for person in [{"dog": "Henry"}, {}, {"dog": None}]:
    try:
        doggo = person['dog']  # can throw KeyError
    except KeyError:
        print("Not a dog person")
        continue  # skip the rest of the loop (since this is a for loop)

    try:
        print(doggo.upper())  # can throw AttributeError
    except AttributeError:
        print("No doggo :(")

A better way is, as Christian suggested:

for person in [{"dog": "Henry"}, {}, {"dog": None}]:
    try:
        doggo = person['dog']  # can throw KeyError
        print(doggo.upper())  # can throw AttributeError
    except KeyError:  # person dict does not contain a "dog"
        print("Not a dog person")
    except AttributeError:  # dog entry cannot be .upper()'d
        print("invalid doggo :(")

Both of which output:

HENRY
Not a dog person
invalid doggo :(

Note this will skip the second set of lines automatically if the first set fails, and lets you do different things based upon which exception occurred.

I think you're confused. After a KeyError above, execution continues after the except blocks. The rest of the try: is skipped, which is what you seem to want:

That's why I can do:

try:
    dct[key] += value
    print("Added.")
except KeyError:
    dct[key] = value
    print("New key.")

Only one of those prints will happen.

TemporalWolf
  • 7,727
  • 1
  • 30
  • 50
  • I do as follows: for person in [...]: try: run a function with msg as an input and if function errors then raise user defined exception. next below I do another try: run another function with msg as an input and if function errors then raise user defined exception. If first try raises an exception then do not execute 2nd try block. if 1st try block does not raise an exception then do execute 2nd try block. Does it sound similar to what you have described? –  May 03 '17 at 09:02
  • @bluedog update your question if you want to add more detail – pvg May 03 '17 at 14:39
  • @BlueDog this will work for you if you implement it as we've said. – TemporalWolf May 03 '17 at 17:10
1

Python allows you to use multiple exception clause in your try/except statements. Add all of your code from the two try blocks into one, and simply use two except clause to catch both potentially errors:

try: 
    #some code
except:
    #some code to e.g. print str
except: 
    #some code to e.g. print str or exit from the program.
Christian Dean
  • 22,138
  • 7
  • 54
  • 87
  • I raise two separate exceptions for two separate try block because both try blocks have different code. So I do not raise two various exceptions for same try block as per your example. –  May 02 '17 at 22:46
  • @BlueDog You don't need to separate try blocks. If you want to skip all the code on the first exception, there is no reason to have two blocks. – TemporalWolf May 02 '17 at 22:47
  • Yes, I want to skip the code down from ex1 try block on the ex1 exception but I do want to execute ex2 try block code if ex1 try block does not raise an exception. –  May 02 '17 at 22:51
  • 1
    @BlueDog but that will happen by itself. When the exception is thrown, controls passes to the relevant exception handler, skipping remaining statements in the try block. If a statement in the try block doesn't raise an exception, execution simply continues. – pvg May 02 '17 at 23:00
  • not necessary. what if ex1 try block exception throws e.g print statement only? the code execution will carry on and execute ex2 try block. –  May 02 '17 at 23:02
  • 1
    @BlueDog What does 'ex1 try block exceptions' mean? If ex1 throws an exception, the exception handler runs and statements between the exception handler and the throw location are simply skipped. It makes no difference what the exception handler actually does – pvg May 02 '17 at 23:04
  • 1
    @BlueDog oh and if you think the handlers will somehow be executed in sequence, no that is not the case. no matter what the individual handler does, only one handler will be called. You don't just drop down and start executing the next one. I think you should just try some of the examples people have posted for yourself. At this point you seem to be trying to explain to us that Python works the way you've misunderstood it to work. – pvg May 02 '17 at 23:08
  • @BlueDog I'm still not exactly sure why this will not work. Of course, you may have to refactor your code a bit, but in my opinion, this would be a more most "Pythonic" method. – Christian Dean May 02 '17 at 23:47
-1

How about this? However, in you should usually be more specific with exceptions, see here: https://docs.python.org/3/tutorial/errors.html for example, use "except ValueError" to only except that one type of error.

try:
    # ex1 code
except:
    # handle the exception
else:
    # ex2 code, will only run if there is no exception in ex1
Jeff
  • 2,040
  • 3
  • 18
  • 19
  • This looks like the most reasonable answer to me. This is what I thought originaly but I do not know what is better: such way od coding or wrapping all in one function block. –  May 02 '17 at 22:53
  • This isn't equivalent since it never handles exceptions raised by the 'ex2 code'. – pvg May 02 '17 at 23:02