Exception Handling - madscatt/sasmol GitHub Wiki
Exception handling: There are two philosophies when it comes to error testing. One is the try and then fix (or EAFP… easier to ask for forgiveness than permission) or the test and the do (LBYL … look before you leap). An example of LBYL is
try:
printable = str(some_object)
except TypeError:
print("unprintable object")
else:
print(printable)
where you first test something … i.e. in the case above, if it can be converted to a string then it can be printed (i.e. print won’t return an error), so then print(). This will fail if for some reason “some_object” changes between the time that it is tested and when it is actually used. This “race” condition may occur for methods that are outside our control. For example, various UDP messaging, NFS, system stuff may cause a failure between the test (ping) and the actual call.
Our decision to use the library is to pre-screen variables and files etc. in the method that is calling the library methods. This will keep the methods in the library shorter and easier to understand.
The types of errors captured in the library are
-
File input & output: does an open file statement work or not?
-
Divide by zero & overflow/underflow: check mathematical operations for fatal issues.
-
Other
Therefore, we will use the general except clause (and sys.exc_info()[0]) bit in the EAFP modality along with the log.error(‘ERROR’,+error) reporting apparatus throughout SASMOL.
This is not required but it is acceptable. Note that in the end we'll pass the sys.exc_info()[0] object if all else fails.
Logging is used to handle program usage and output. See the "Logging page" for more details.
class log():
def error(self, message):
print '\n'+message+'\n'
raise
log = log()
For opening a file and reading lines into an object
try:
filename = 'data.txt'
file = open(filename).readlines()
except IOError as error:
log.error("ERROR: I/O error({0}): {1}".format(error.errno, error.strerror) + " : " + filename)
except:
log.error("ERROR: Unexpected error:" + str(sys.exc_info()[0]))
With a file open one should iterate through the lines and capture any existence or format errors.
try:
for line in file:
value = int(line.strip())
except ValueError:
log.error("ERROR: Could not convert data to an integer: \nline number in file = " + str(file.index(line) + 1) + "\nvalue = " + str(line))
except:
log.error("ERROR: Unexpected error:" + str(sys.exc_info()[0]))
Minimize the amount of code in a try/except block. The larger the body of the try, the more likely that an exception will be raised by a line of code that you didn't expect to raise an exception. In those cases, the try/except block hides a real error.
Never use catch-all except: statements, or catch Exception or StandardError, unless you are re-raising the exception or in the outermost block in your thread (and printing an error message). Python is very tolerant in this regard and except: it will catch everything including misspelled names, sys.exit() calls, Ctrl+C interrupts, unittest failures and all kinds of other exceptions that you simply don't want to catch.
Use the finally clause to execute code whether or not an exception is raised in the try block. This is often useful for cleanup, i.e., closing a file.
Here are a few links to some information.
https://wiki.python.org/moin/HandlingExceptions
http://www.jeffknupp.com/blog/2013/02/06/write-cleaner-python-use-exceptions/