Presentation is loading. Please wait.

Presentation is loading. Please wait.

Exceptions Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Similar presentations


Presentation on theme: "Exceptions Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See"— Presentation transcript:

1 Exceptions Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See http://software-carpentry.org/license.html for more information. Testing

2 Exceptions Things go wrong

3 TestingExceptions Things go wrong External

4 TestingExceptions Things go wrong External –Missing or badly-formatted file

5 TestingExceptions Things go wrong External –Missing or badly-formatted file Internal

6 TestingExceptions Things go wrong External –Missing or badly-formatted file Internal –Bug in code

7 TestingExceptions Things go wrong External –Missing or badly-formatted file Internal –Bug in code

8 TestingExceptions Things go wrong External –Missing or badly-formatted file Internal –Bug in code Handling errors sensibly is easy

9 TestingExceptions Option #1: return status code

10 TestingExceptions Option #1: return status code params, status = read_params(param_file) if status != OK: log.error('Failed to read', param_file) sys.exit(ERROR) grid, status = read_grid(grid_file) if status != OK: log.error('Failed to read', grid_file) sys.exit(ERROR)

11 TestingExceptions Option #1: return status code This is what we really care about params, status = read_params(param_file) if status != OK: log.error('Failed to read', param_file) sys.exit(ERROR) grid, status = read_grid(grid_file) if status != OK: log.error('Failed to read', grid_file) sys.exit(ERROR)

12 TestingExceptions Option #1: return status code The rest is error handling params, status = read_params(param_file) if status != OK: log.error('Failed to read', param_file) sys.exit(ERROR) grid, status = read_grid(grid_file) if status != OK: log.error('Failed to read', grid_file) sys.exit(ERROR)

13 TestingExceptions Hard to see the forest for the trees

14 TestingExceptions Hard to see the forest for the trees Expected flow of control

15 TestingExceptions Hard to see the forest for the trees Expected flow of control Error handling

16 TestingExceptions Hard to see the forest for the trees Expected flow of control Error handling So people don't even try to handle errors

17 TestingExceptions Hard to see the forest for the trees Expected flow of control Error handling So people don't even try to handle errors Which makes them harder to find and fix when they do occur

18 TestingExceptions Option #2: use exceptions

19 TestingExceptions Option #2: use exceptions Separate "normal" operation from code that handles "exceptional" cases

20 TestingExceptions Option #2: use exceptions Separate "normal" operation from code that handles "exceptional" cases Make both easier to understand

21 TestingExceptions Rearrange this... params, status = read_params(param_file) if status != OK: log.error('Failed to read', param_file) sys.exit(ERROR) grid, status = read_grid(grid_file) if status != OK: log.error('Failed to read', grid_file) sys.exit(ERROR)

22 TestingExceptions...to put "normal" code in one place... params, status = read_params(param_file) if status != OK: log.error('Failed to read', param_file) sys.exit(ERROR) grid, status = read_grid(grid_file) if status != OK: log.error('Failed to read', grid_file) sys.exit(ERROR) params = read_params(param_file) grid = read_grid(grid_file)

23 TestingExceptions...and error handling code in another params, status = read_params(param_file) if status != OK: log.error('Failed to read', param_file) sys.exit(ERROR) grid, status = read_grid(grid_file) if status != OK: log.error('Failed to read', grid_file) sys.exit(ERROR) params = read_params(param_file) grid = read_grid(grid_file) log.error('Failed to read', filename) sys.exit(ERROR)

24 TestingExceptions...and error handling code in another params, status = read_params(param_file) if status != OK: log.error('Failed to read', param_file) sys.exit(ERROR) grid, status = read_grid(grid_file) if status != OK: log.error('Failed to read', grid_file) sys.exit(ERROR) Only need one copy of the error handling code params = read_params(param_file) grid = read_grid(grid_file) log.error('Failed to read', filename) sys.exit(ERROR)

25 TestingExceptions Join the two parts with try and except params, status = read_params(param_file) if status != OK: log.error('Failed to read', param_file) sys.exit(ERROR) grid, status = read_grid(grid_file) if status != OK: log.error('Failed to read', grid_file) sys.exit(ERROR) try: params = read_params(param_file) grid = read_grid(grid_file) except: log.error('Failed to read', filename) sys.exit(ERROR)

26 TestingExceptions You have seen exceptions before

27 TestingExceptions You have seen exceptions before >>> open('nonexistent.txt', 'r') IOError: No such file or directory: 'nonexistent.txt'

28 TestingExceptions You have seen exceptions before >>> open('nonexistent.txt', 'r') IOError: No such file or directory: 'nonexistent.txt' >>> values = [0, 1, 2] >>> values[99] IndexError: list index out of range

29 TestingExceptions Use try and except to deal with them yourself

30 TestingExceptions Use try and except to deal with them yourself >>> try:... reader = open('nonexistent.txt', 'r')... except IOError:... print 'Whoops!' Whoops!

31 TestingExceptions Use try and except to deal with them yourself >>> try:... reader = open('nonexistent.txt', 'r')... except IOError:... print 'Whoops!' Whoops! Blue indicates regular output

32 TestingExceptions Use try and except to deal with them yourself >>> try:... reader = open('nonexistent.txt', 'r')... except IOError:... print 'Whoops!' Whoops! Try to do this...

33 TestingExceptions Use try and except to deal with them yourself >>> try:... reader = open('nonexistent.txt', 'r')... except IOError:... print 'Whoops!' Whoops!...and do this if an IO error occurs

34 TestingExceptions Use try and except to deal with them yourself...and do this if an IO error occurs 'IOError' is how Python reports 'file not found' >>> try:... reader = open('nonexistent.txt', 'r')... except IOError:... print 'Whoops!' Whoops!

35 TestingExceptions Can put many lines of code in a try block

36 TestingExceptions Can put many lines of code in a try block And handle several errors afterward

37 TestingExceptions Can put many lines of code in a try block And handle several errors afterward try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError: log_error_and_exit('IO error') except ArithmeticError: log_error_and_exit('Arithmetic error')

38 TestingExceptions Try to do this try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError: log_error_and_exit('IO error') except ArithmeticError: log_error_and_exit('Arithmetic error') Can put many lines of code in a try block And handle several errors afterward

39 TestingExceptions try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError: log_error_and_exit('IO error') except ArithmeticError: log_error_and_exit('Arithmetic error') Handle I/O errors here Can put many lines of code in a try block And handle several errors afterward

40 TestingExceptions try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError: log_error_and_exit('IO error') except ArithmeticError: log_error_and_exit('Arithmetic error') and numerical errors here Can put many lines of code in a try block And handle several errors afterward

41 TestingExceptions try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError: log_error_and_exit('IO error') except ArithmeticError: log_error_and_exit('Arithmetic error') These messages aren't very helpful Can put many lines of code in a try block And handle several errors afterward

42 TestingExceptions Python 2.6 try: x = 1/0 except Exception, error: print error

43 TestingExceptions Python 2.6 try: x = 1/0 except Exception, error: print error Stores information about what went wrong

44 TestingExceptions Python 2.6 try: x = 1/0 except Exception, error: print error Stores information about what went wrong Different information for different kinds of errors

45 TestingExceptions Python 2.6 try: x = 1/0 except Exception, error: print error Python 2.7 try: x = 1/0 except Exception as error: print error More readable

46 TestingExceptions Better error messages

47 TestingExceptions try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError as err: log_error_and_exit('Cannot read/write' + err.filename) except ArithmeticError as err: log_error_and_exit(err.message) Better error messages

48 TestingExceptions try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError as err: log_error_and_exit('Cannot read/write' + err.filename) except ArithmeticError as err: log_error_and_exit(err.message) Better error messages

49 TestingExceptions try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError as err: log_error_and_exit('Cannot read/write' + err.filename) except ArithmeticError as err: log_error_and_exit(err.message) Better error messages Help user figure out which file

50 TestingExceptions try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError as err: log_error_and_exit('Cannot read/write' + err.filename) except ArithmeticError as err: log_error_and_exit(err.message) Better error messages No worse than the default

51 TestingExceptions A question of style

52 TestingExceptions A question of style try: grid = read_grid(grid_file) except IOError: grid = default_grid()

53 TestingExceptions A question of style if file_exists(grid_file): grid = read_grid(grid_file) else: grid = default_grid() try: grid = read_grid(grid_file) except IOError: grid = default_grid()

54 TestingExceptions try: grid = read_grid(grid_file) except IOError: grid = default_grid() A question of style if file_exists(grid_file): grid = read_grid(grid_file) else: grid = default_grid() Use exceptions for exceptional cases

55 TestingExceptions Another question of style

56 TestingExceptions Another question of style But first...

57 TestingExceptions Exceptions can be thrown a long way

58 TestingExceptions try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError as err: log_error_and_exit('Cannot read/write' + err.filename) except ArithmeticError as err: log_error_and_exit(err.message) Exceptions can be thrown a long way

59 TestingExceptions try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError as err: log_error_and_exit('Cannot read/write' + err.filename) except ArithmeticError as err: log_error_and_exit(err.message) These are function calls Exceptions can be thrown a long way

60 TestingExceptions Any errors they don't catch... Exceptions can be thrown a long way try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError as err: log_error_and_exit('Cannot read/write' + err.filename) except ArithmeticError as err: log_error_and_exit(err.message)

61 TestingExceptions Exceptions can be thrown a long way try: params = read_params(param_file) grid = read_grid(grid_file) entropy = lee_entropy(params, grid) write_entropy(entropy_file, entropy) except IOError as err: log_error_and_exit('Cannot read/write' + err.filename) except ArithmeticError as err: log_error_and_exit(err.message)...are caught and handled here

62 TestingExceptions "Throw low, catch high"

63 TestingExceptions "Throw low, catch high" Many places where errors might occur

64 TestingExceptions "Throw low, catch high" Many places where errors might occur Only a few where they can sensibly be handled

65 TestingExceptions "Throw low, catch high" Many places where errors might occur Only a few where they can sensibly be handled A linear algebra library doesn't know how its callers will want to report errors...

66 TestingExceptions "Throw low, catch high" Many places where errors might occur Only a few where they can sensibly be handled A linear algebra library doesn't know how its callers will want to report errors......so it shouldn't try to handle them itself

67 TestingExceptions You can raise exceptions yourself

68 TestingExceptions You can raise exceptions yourself should

69 TestingExceptions You can raise exceptions yourself should def read_grid(grid_file): '''Read grid, checking consistency.''' data = read_raw_data(grid_file) if not grid_consistent(data): raise Exception('Inconsistent grid: ' + grid_file) result = normalize_grid(data) return result

70 TestingExceptions You can raise exceptions yourself should def read_grid(grid_file): '''Read grid, checking consistency.''' data = read_raw_data(grid_file) if not grid_consistent(data): raise Exception('Inconsistent grid: ' + grid_file) result = normalize_grid(data) return result

71 TestingExceptions You can define new types of exceptions too

72 TestingExceptions You can define new types of exceptions too should

73 TestingExceptions You can define new types of exceptions too should Need to understand classes and objects first

74 July 2010 created by Greg Wilson Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See http://software-carpentry.org/license.html for more information.


Download ppt "Exceptions Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See"

Similar presentations


Ads by Google