- Runtime errors
occur only when the the program is run
- They occur when a value makes a statement fail
- If the program is run again with a different value no runtime error would occur
- A common way to get a runtime error is to open a file that does not exist
$ ./file_open.py
Filename: xxxxxx
Traceback (most recent call last):
File "./file_open.py", line 6, in <module>
file = open(filename, "r")
FileNotFoundError: [Errno 2] No such file or directory: 'xxxxxx'
- If you try to open a file for which you have no permission you will get another type of runtime error
$ ./file_open.py
Filename: unreadable.txt
Traceback (most recent call last):
File "./file_open.py", line 6, in <module>
file = open(filename, "r")
PermissionError: [Errno 13] Permission denied: 'unreadable.txt'
- Giving a conversion function a value it can't handle is another runtime error
$ ./int_request.py
Integer: five
Traceback (most recent call last):
File "./int_request.py", line 5, in <module>
number = int(input("Integer: "))
ValueError: invalid literal for int() with base 10: 'five'
- Or you can give a function an argument with the wrong type
>>> round("five")
Traceback (most recent call last):
File "<stdin>, line 1, in <module>
TypeError: type str doesn't define __round__ method
- Or dividing by zero
$ ./divide_two_numbers.py
Numerator: 5
Denominator: 0
Traceback (most recent call last):
File "./divide_two_numbers.py", line 7, in <module>
result = numerator / denominator
ZeroDivisionError: division by zero
- The problems that cause runtime errors are called
exceptions
- In the scripts that processed temperature data the filename was written into the code
file = open('temps.txt', 'r')
- A more realistic script would ask the user for the filename
- But if the user enters the wrong filename you will get a runtime error
$ ./temps_average_2.py
Filename: xxx
Traceback (most recent call last):
File "./temps_average_2.py", line 7, in <module>
file = open(filename, 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'xxx'
- To fix this, we might be tempted to put the call to
open
in the try
block
filename = input("Filename: ")
try:
file = open(filename, 'r')
except:
print('Cannot open', filename)
count = 0
total = 0
for line in file:
count += 1
date, temp = line.split()
temp = int(temp)
total += temp
average = round(total/count, 2)
print('Average:', average)
- This fixes one problem but creates another
$ ./temps_average_3.py
Filename: xxx
Cannot open xxx
Traceback (most recent call last):
File "./temps_average_3.py", line 15, in <module>
for line in file:
NameError: name 'file' is not defined
- We depend on the
open
statement working for the rest of the script to work
- To fix this, we can put every statement that needs the file object
inside the
try
block
filename = input("Filename: ")
try:
file = open(filename, 'r')
count = 0
total = 0
for line in file:
count += 1
date, temp = line.split()
temp = int(temp)
total += temp
average = round(total/count, 2)
print('Average:', average)
except:
print('Cannot open', filename)
- This version better handles a bad filename
$ ./temps_average_4.py
Filename: xxx
Cannot open xxx
- Let's look at some of the more common types of exception objects
- When you try to open a file that does not exists you get a FileNotFoundError
exception object
>>> open("xxx.txt","r")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'xxx.txt'
- If you try to open a file for which you do not have permission you will get a
PermissionError object
file = open("test.txt","r")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
PermissionError: [Errno 13] Permission denied: 'test.txt'
- If a conversion function gets the wrong type of argument a
ValueError object is created
>>> number = float(input("Number: "))
Number: five
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'five'
>>> number = float(input("Number: "))
Number: 5..4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: could not convert string to float: '5..4'
- If you
import
a module that doesn't exist
you get an ImportError object
>>> import foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'foo'
- If you try to divide a number by zero the interpreter will create a
ZeroDivisionError exception object
>>> print(5/0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero