Grace Murray Hopper popularised the term bug after in 1947 her team traced an error in the Mark II to a moth trapped in a relay.
def even_or_odd(num):
if num % 2 == 0:
return 'even'
else:
return 'odd'
even_or_odd(42.7)
'odd'
even_or_odd('42')
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In [3], line 1 ----> 1 even_or_odd('42') Cell In [1], line 2, in even_or_odd(num) 1 def even_or_odd(num): ----> 2 if num % 2 == 0: 3 return 'even' 4 else: TypeError: not all arguments converted during string formatting
def even_or_odd(num):
num = int(num) # We expect input to be integer or convertible into one
if num % 2 == 0:
return 'even'
else:
return 'odd'
even_or_odd(42.7)
'even'
even_or_odd('42')
'even'
Fixing a buggy program is a process of confirming, one by one, that the many things you believe to be true about the code actually are true. When you find that one of your assumptions is not true, you have found a clue to the location (if not the exact nature) of a bug.
Norman Matloff
When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.
Arthur Conan Doyle
print()
¶print()
statement can be used to check the internal state of a program during evaluationvars()
or locals()
to reveal all local objectspdb
)def calculate_median(lst):
lst.sort()
n = len(lst)
m = (n + 1)//2
if n % 2 == 1:
median = lst[m]
else:
median = sum(lst[m-1:m])/2
return median
l1 = [1, 2, 3]
l2 = [0, 1, 1, 2]
calculate_median(l1)
3
calculate_median(l2)
0.5
print()
example¶def calculate_median(lst):
lst.sort()
n = len(lst)
m = (n + 1)//2
print(m)
if n % 2 == 1:
median = lst[m]
else:
median = sum(lst[m-1:m])/2
return median
l1 = [1, 2, 3]
l2 = [0, 1, 1, 2]
calculate_median(l1)
2
3
calculate_median(l2)
2
0.5
print()
and vars()
example¶def calculate_median(lst):
lst.sort()
n = len(lst)
m = (n + 1)//2
print(vars())
if n % 2 == 1:
median = lst[m]
else:
median = sum(lst[m-1:m])/2
return median
l1 = [1, 2, 3]
l2 = [0, 1, 1, 2]
calculate_median(l1)
{'lst': [1, 2, 3], 'n': 3, 'm': 2}
3
calculate_median(l2)
{'lst': [0, 1, 1, 2], 'n': 4, 'm': 2}
0.5
print()
example continued¶def calculate_median(lst):
lst.sort()
n = len(lst)
m = (n + 1)//2
print(m)
if n % 2 == 1:
median = lst[m-1]
else:
print(sum(lst[m-1:m]))
median = sum(lst[m-1:m])/2
return median
l1 = [1, 2, 3]
l2 = [0, 1, 1, 2]
calculate_median(l1)
2
2
calculate_median(l2)
2 1
0.5
77001 23 + # Raises an exception 'SyntaxError'
Cell In [23], line 1 77001 23 + # Raises an exception 'SyntaxError' ^ SyntaxError: invalid syntax
'4' < 3 # Raises an exception 'TypeError'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In [24], line 1 ----> 1 '4' < 3 TypeError: '<' not supported between instances of 'str' and 'int'
l = [0, 1, 2, 3]
l[4] # Raises an exception 'IndexError'
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) Cell In [25], line 2 1 l = [0, 1, 2, 3] ----> 2 l[4] IndexError: list index out of range
try-except
construct for catching and handling exceptionstry:
<code_block>
except:
<exception_code_block>
def even_or_odd(num):
try:
num = int(num)
except:
print('Input cannot be converted into integer')
return None
if num % 2 == 0:
return 'even'
else:
return 'odd'
even_or_odd('forty-two')
Input cannot be converted into integer
even_or_odd([0, 1, 2])
Input cannot be converted into integer
try:
<code_block>
except <exception_name_1>:
<exception_code_block_2>
except <exception_name_2>:
<exception_code_block_2>
...
except <exception_name_n> as <variable>:
<exception_code_block_n>
def even_or_odd(num):
try:
num = int(num)
except ValueError:
print('Input cannot be converted into integer')
return None
if num % 2 == 0:
return 'even'
else:
return 'odd'
even_or_odd('forty-two')
Input cannot be converted into integer
even_or_odd([0, 1, 2])
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In [31], line 1 ----> 1 even_or_odd([0, 1, 2]) Cell In [29], line 3, in even_or_odd(num) 1 def even_or_odd(num): 2 try: ----> 3 num = int(num) 4 except ValueError: 5 print('Input cannot be converted into integer') TypeError: int() argument must be a string, a bytes-like object or a real number, not 'list'
def even_or_odd(num):
try:
num = int(num)
except ValueError:
print('Input cannot be converted into integer')
return None
except TypeError as msg: # Exception can also be assigned to a variable
print(msg)
return None
if num % 2 == 0:
return 'even'
else:
return 'odd'
even_or_odd('forty-two')
Input cannot be converted into integer
even_or_odd([0, 1, 2])
int() argument must be a string, a bytes-like object or a real number, not 'list'
else
after try-except
construct allows to execute arbitrary code if no exception had been raisedfinally
allows to execute some code block regardless of the result of try
blocktry:
<code_block>
except <exception_name_1>:
<exception_code_block_2>
except (<exception_name_2>, <exception_name_3>):
<exception_code_block_2_3>
...
except <exception_name_n> as <variable>:
<exception_code_block_n>
else:
<alternative_code_block>
finally:
<another_code_block>
def even_or_odd(num):
try:
num = int(num)
except ValueError:
print('Input cannot be converted into integer')
return None
except TypeError as msg:
print(msg)
return None
else:
print('Checking ' + str(num)) # Code block gets executed if no exception had been raised
if num % 2 == 0:
return 'even'
else:
return 'odd'
even_or_odd('forty-two')
Input cannot be converted into integer
even_or_odd(42.7)
Checking 42
'even'
def even_or_odd(num):
def cast_int(num):
try:
new_num = int(num)
except ValueError:
print('Input cannot be converted into integer')
except TypeError as msg:
print(msg)
else:
print('Converted '+ str(num) + ' to ' + str(new_num))
return new_num
num = cast_int(num)
if num is not None:
if num % 2 == 0:
return 'even'
else:
return 'odd'
even_or_odd('forty-two')
Input cannot be converted into integer
even_or_odd(42.7)
Converted 42.7 to 42
'even'
even_or_odd([0, 1, 2])
int() argument must be a string, a bytes-like object or a real number, not 'list'
raise
statement is used to force a specified exception to occurraise <exception_name>
or
raise <exception_name>(<message>)
raise IndexError
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) Cell In [42], line 1 ----> 1 raise IndexError IndexError:
def calculate_median(lst):
for i in range(len(lst)):
try:
lst[i] = float(lst[i])
except:
raise ValueError('All elements of the list must be numeric')
lst.sort()
n = len(lst)
m = (n + 1)//2
if n % 2 == 1:
median = lst[m-1]
else:
median = sum(lst[m-1:m+1])/2
return median
l = [0, 'one', 1, 2]
calculate_median(l)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In [43], line 4, in calculate_median(lst) 3 try: ----> 4 lst[i] = float(lst[i]) 5 except: ValueError: could not convert string to float: 'one' During handling of the above exception, another exception occurred: ValueError Traceback (most recent call last) Cell In [45], line 1 ----> 1 calculate_median(l) Cell In [43], line 6, in calculate_median(lst) 4 lst[i] = float(lst[i]) 5 except: ----> 6 raise ValueError('All elements of the list must be numeric') 7 lst.sort() 8 n = len(lst) ValueError: All elements of the list must be numeric
Exception | Description |
---|---|
SyntaxError |
Parser encountered a syntax error |
IndexError |
Sequence subscript is out of range |
NameError |
Local or global name is not found |
TypeError |
Operation or function is applied to an object of inappropriate type |
ValueError |
Operation or function receives an argument that has the right type but an inappropriate value |
OSError |
I/O failures such as “file not found” or “disk full” |
ImportError |
import statement had problems with loading a module |
AssertionError |
assert statement failed |
assert
statement provides another way of raising exceptions if expectations are not metassert <boolean_expression>
or
assert <boolean_expression>, <message>
assert False, 'Nobody expects the Spanish Inquisition!'
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) Cell In [46], line 1 ----> 1 assert False, 'Nobody expects the Spanish Inquisition!' AssertionError: Nobody expects the Spanish Inquisition!
def is_positive(num):
assert num != 0, 'Input must be non-zero'
if num > 0:
return True
else:
return False
is_positive(0)
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) Cell In [48], line 1 ----> 1 is_positive(0) Cell In [47], line 2, in is_positive(num) 1 def is_positive(num): ----> 2 assert num != 0, 'Input must be non-zero' 3 if num > 0: 4 return True AssertionError: Input must be non-zero
unittest
moduledef calculate_median(lst):
lst.sort()
n = len(lst)
m = (n + 1)//2
if n % 2 == 1:
median = lst[m-1]
else:
median = sum(lst[m-1:m+1])/2
return median
# Test the equality of the result of function call and some value
def test_equal(func, value):
assert func == value
print('Equality test passed')
l = [0, 1, 1, 2, 3]
test_equal(calculate_median(l), 1)
Equality test passed