Download presentation
Presentation is loading. Please wait.
Published byAshley Craig Modified over 9 years ago
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.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.