3

I'm writing a custom backup script in Python. Sometimes the mkdir function or the print function or whatever function are failing for diverse reasons. Such exceptions stop the whole script and halt the backup in the middle, which is very frustrating. So far, I've managed these problems by adding try: ... except: ... statements and properly managing these exceptions. However, one day some other statement or function might raise an exception as well because of some other reason that hasn't been triggered yet.

Is there a way to tell a script to proceed anyway? An equivalent of wrapping every single statement of the code in a try: ... except: pass clause? A log would be better of course.

I've noticed that when programming with GUI toolkits like Tkinter, the application keeps running even if exceptions are raised. Is it possible to accomplish this type of thing with the console?

Andy
  • 136
  • 2
  • 7
  • 1
    Instead of wrapping every statement in `try...except` blocks, you should probably be doing more validation and testing in your code. If a function depends on an input list with 5 items, test that the list *has* 5 items. – MattDMo Nov 22 '15 at 21:59
  • That's somewhat un-pythonic - as it's directly goes against "Easier to Ask Forgiveness that Permission". – Tom Dalton Nov 22 '15 at 22:04
  • 2
    What you're asking doesn't make any sense. Say the mkdir function failed; if you ignored the exception, what would you expect the code that was intending to use that directory to do? – Daniel Roseman Nov 22 '15 at 22:05
  • @TomDalton: Just what I was thinking! See [EAFP](https://docs.python.org/2/glossary.html#term-eafp) vs. [LBYL](https://docs.python.org/2/glossary.html#term-lbyl). – Falko Nov 22 '15 at 22:06
  • 1
    Possible duplicate of [Python: about catching ANY exception](http://stackoverflow.com/questions/4990718/python-about-catching-any-exception) – Pynchia Nov 22 '15 at 22:08

7 Answers7

5

There actually is a module that is supposed to do exactly that: https://github.com/ajalt/fuckitpy.

Although it was obviously written as a joke. I cannot imagine a situation where doing something like that is a good idea. God, I can't believe I'm even suggesting that as a solution.

What you should do instead is identify what lines of code can produce what kind of errors, and handle those errors properly. There is only so much places where errors can actually happen - mostly while interfacing with outside systems, including filesystem, network, user input etc. And remember that actually failing is often better than continuing "work" and messing up your data, files and so on. Exceptions are there for a reason, they are not a result of Guido's malice.

thule
  • 4,034
  • 21
  • 31
3

Python has 'BaseException' as the base class for Exception classes. You can catch and ignore the base class Exception and that will cover all exceptions.

try
    ... your code here ...
except BaseException as exp:
    print "A General Exception Occurred"
Kanwar Saad
  • 2,138
  • 2
  • 21
  • 27
3

Python has no way of doing that, and for good reasons.

It seems you're confused about what does it mean to write "robust" software: a robust program is not a program that is hard to kill and that will keep running no matter what, but a program that will handle edge cases properly. Keeping running is NOT enough... keeping running doing sensible things is the key point.

Unfortunately there's no way to do reasonable things automatically and you've to think on a case-by-case basis how to handle the error.

Beware that if a program has a lot of catch it's rarely a good program. Exceptions are meant to be raised in a lot of places and caught almost nowhere.

Note also that every catch is potentially a source of bugs... for example:

try:
    print my_dict[foo()]
except KeyError:
    ...

cannot distinguish if the KeyError is coming for accessing a non-existing key in my_dict or if instead escaped from foo(). Rarely the two cases should be handled the same way...

Better is to write:

key = foo()
if key in my_dict:
    print my_dict[key]
else:
    ...

so that only the side case of missing key in my_dict is handled and instead a KeyError exception will stop the program (stopping a program when you're not sure of what it's doing is the only reasonable thing to do).

l__flex__l
  • 1,388
  • 1
  • 16
  • 22
6502
  • 112,025
  • 15
  • 165
  • 265
  • 1
    "Easier to ask for forgiveness than permission. This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C." ~ python docs – l__flex__l Jan 19 '17 at 14:26
1
try:
   # code segment
except:
   pass

pass keyword will ignore all the exceptions

BasuruK
  • 61
  • 1
  • 8
0

Normally, this one should catch everything:

try:
   ....
except:
   pass

Only problem is, that you don't get the exception object with this syntax, but that was not asked for in this case.

Juergen
  • 12,378
  • 7
  • 39
  • 55
0

You can add a general except block like @Kanwar Saad proposed. The question is, can you continue with your program in a valid state after the exception has been raised?

From the Zen of Python:

Errors should never pass silently.
Unless explicitly silenced.

Trying to catch all exceptions you know is in my opinion is the best way to go here. If you can not explicitly catch an exception you should not try to work around it. You (and your users) should know what exactly went wrong, otherwise your code might become a nightmare to debug.

If you are worried about losing backup data maybe you could do something like this:

def save_unfinished_backup():
    # try to find a graceful exit without losing any data

try:
    # some code
except OSError:
    # handle oS Errors
except Exception:
    save_unfinished_backup()
    raise

This way you get both: A chance to fend of data loss and the exact error to debug it.

I hope this helps!


On a funny note: You could also use the fuckit module. Which silences ALL errors, including syntax errors. Do not, ever, use this in productive code though.

This should work perfectly. It will not print the "foo", but you will reach the print("bar") without a crash.

import fuckit

with fuckit:
    prnt("foo")

print("bar")
m00am
  • 5,910
  • 11
  • 53
  • 69
0

New answer for new Gen...

Python now ships with suppress(), this tells the interpreter to suppress the indicated exceptions while running.

Can be easily imported used as below

from contextlib import suppress
with suppress(ValueError):
    int('this wont catch')
print('yea')

The above will work, wont raise the ValueError exception of changing invalid int string to int...

It's more clean than third party libraries.

Happy Hacking

emanuel sanga
  • 815
  • 13
  • 17