Syntax Errors
-------------
- parsing errors
- common errors when
you are still learning python
>>>
while True print('Hello world')
File "", line 1
while True print('Hello world')
^
SyntaxError:
invalid syntax
Exceptions
----------
- errors occured
during execution
- types:
a. built-in exceptions
b. user-definedexceptions
- can be handled
Examples of
Built-in exceptions
|
>>>
10 * (1/0)
Traceback
(most recent call last):
File "
ZeroDivisionError:
division by zero
>>>
4 + spam*3
Traceback
(most recent call last):
File "
NameError:
name 'spam' is not defined
>>>
'2' + 2
Traceback
(most recent call last):
File "
TypeError:
Can't convert 'int' object to str implicitly
|
EOFError
|
- means you hit
CTRL + D
- useful in input()
and raw_input()
|
Handling Exceptions
-------------------
- exceptions can be
handled use `try .. except` clause
- execution is as
follows:
* First, the try clause (the statement(s)
between the try and except
keywords) is executed.
* If no exception occurs, the except clause
is skipped and execution of the
try statement is finished.
* If an exception occurs during execution
of the try clause, the rest of
that try clause is skipped. Then if its
type matches the exception named
after the except keyword, the except
clause is executed, and then
execution continues after the try
statement (jumping to another except or
finally clause).
* If an exception occurs which does not
match the exception named in the
except clause, it is passed or to outer
try statements; if no handler is
found, it is an unhandled exception and
execution stops with a message
- `try` statement can
have multiple `except` clause or handlers
- a handler is the
clause within `except` statement
* handles exceptions that occure in the
corresponding `try` statement
* doesn't handle exceptions generated on
other handlers within same `try`
statement
Basic `try ..
except` clause
|
>>>
while True:
... try:
... x = int(input("Please enter a
number: "))
... break
... except ValueError:
... print("Oops! That was no valid number. Try again...")
...
|
Multiple exceptions
|
...
except (RuntimeError, TypeError, NameError):
... pass
|
Class in except
clause
*NEED MORE UNDERSTADNING* |
A class in an
except clause is compatible with an exception if it is the
same class or a
base class thereof (but not the other way around — an
except clause
listing a derived class is not compatible with a base
class). For
example, the following code will print B, C, D in that order:
class
B(Exception):
pass
class
C(B):
pass
class
D(C):
pass
for
cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
Note that if the
except clauses were reversed (with except B first),
it would have
printed B, B, B — the first matching except clause is
triggered.
|
`except` for
everything else
|
A last `except`
clause may serve as a wildcard.
import
sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except
OSError as err:
print("OS error:
{0}".format(err))
except
ValueError:
print("Could not convert data to an
integer.")
except:
print("Unexpected error:",
sys.exc_info()[0])
raise
Be careful in using it since it can mask a real programming error. |
Using `else` clause
in `try`
statements |
An optional `else`
statement can follow a `try` statement. The `else` clause
will be executed when there is no exception encountered.
for
arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()),
'lines')
f.close()
Using `else` is sometimes better than putting additional code in the `try` statement because it prevents catching an exception that wasn't raise by the code being protected by the `try .. except` statement. |
Exception arguments
|
`except` clause may
store the exception into a variable.
try:
raise Exception('spam', 'eggs')
except
Exception as inst:
print(type(inst)) # the exception instance
print(inst.args) #
arguments stored in .args
print(inst) # __str__ allows args to be printed
directly,
# but may be overridden in exception subclasses
x, y =
inst.args # unpack args
x, y = inst # unpack args
print('x =', x)
print('y =', y)
|
Exceptions inside
functions
|
Exceptions can also
be handled even they are generated from inside a function.
>>>
def this_fails():
... x = 1/0
...
>>>
try:
... this_fails()
...
except ZeroDivisionError as err:
... print('Handling run-time error:', err)
...
Handling
run-time error: division by zero
|
Raising Exceptions
------------------
- allows programmers
to force an exception to occur
- syntax: `raise
ExceptionName`
- types of
ExceptionNames:
a. exception instance
b. exception class (class derived from an
exception)
Raising an
exception
|
>>>
raise NameError('HiThere')
Traceback
(most recent call last):
File "
NameError:
HiThere
|
Using
exception class
|
raise ValueError # shorthand for 'raise ValueError()'
|
Re-raising
an exception
|
This can
be used if you want to determine whether an exception occured but you dont't
want to
handle it.
>>>
try:
... raise NameError('HiThere')
...
except NameError:
... print('An exception flew by!')
... raise
...
An
exception flew by!
Traceback
(most recent call last):
File "
NameError:
HiThere
|
User-defined Exceptions
-----------------------
- usually derived
from `Exception` class
- common practice:
1. create a base class for that module
2. create subclasses for different error
conditions
- standard naming
convention appending "Error" at the exception name
Using a
user-defined exception
|
This
program asks the user for a number. If the number is smaller than, it will
raise
`ValueTooSmallError` and `ValueTooLargeError` if number is larger.
#
define Python user-defined exceptions
class
Error(Exception):
"""Base class for other
exceptions"""
pass
class
ValueTooSmallError(Error):
"""Raised when the input
value is too small"""
pass
class
ValueTooLargeError(Error):
"""Raised when the input
value is too large"""
pass
# our
main program
#
user guesses a number until he/she gets it right
# you
need to guess this number
number
= 10
while
True:
try:
i_num = int(input("Enter a
number: "))
if i_num < number:
raise ValueTooSmallError
elif i_num > number:
raise ValueTooLargeError
break
except ValueTooSmallError:
print("This value is too small,
try again!")
print()
except ValueTooLargeError:
print("This value is too large,
try again!")
print()
print("Congratulations!
You guessed it correctly.")
Here is
a sample output of the program:
Enter
a number: 12
This
value is too large, try again!
Enter
a number: 0
This
value is too small, try again!
Enter
a number: 8
This
value is too small, try again!
Enter
a number: 10
Congratulations!
You guessed it correctly.
|
Clean-up actions: `finally` statement
-------------------------------------
- `finally` statement
allows to execute actions regardless of the outcome of
`try` clause
- when does `finally`
clause run?
* when there is no exception
-> `try` executes
-> `finally` executes
* when there is a handled exception
-> exception is handled
-> `finally` executes
* when there is an unhandled exception
-> `finally` executes
-> exception is re-reaised
* when `try` ends in a break, continue,
etc..
- uses:
a. enables programs that must free up
resources regardless of the
outcome of the main code (e.g network
connections, files, etc.)
Simple demo
|
>>>
def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print("division by zero!")
... else:
... print("result is", result)
... finally:
... print("executing finally
clause")
...
>>>
divide(2, 1)
result
is 2.0
executing
finally clause
>>>
divide(2, 0)
division
by zero!
executing
finally clause
>>>
divide("2", "1")
executing
finally clause
Traceback
(most recent call last):
File "
File "
TypeError:
unsupported operand type(s) for /: 'str' and 'str'
|
Another example
|
The `with`
statement can be used to open and close a file regardless on what action you
have done on the file object.
for
line in open("myfile.txt"):
print(line, end="")
|
Assertions
----------
- way of testing a
condition
* if true, returns nothing and program
continues
* if false, it raises an
"AssertionError"
- uses:
a. used to trace a bug in a program
(internal self check)
b. informs programmer about unrecoverable
errors
- not used to catch
an error and handle it
Assertion in action
|
As an example, this
function computes the final price of a product after applying a
discount and makes sure that the discounted price is always greater than $ 0 and is less than the original price of the product.
def
apply_discount(product, discount):
price = int(product['price'] * (1.0 -
discount))
assert 0 <= price <=
product['price']
return
price
So when we applied a valid discount, the program works neatly without errors.
#
# Our
example product: Nice shoes for $149.00
#
>>>
shoes = {'name': 'Fancy Shoes', 'price': 14900}
#
# 25%
off -> $111.75
#
>>>
apply_discount(shoes, 0.25)
11175
But when
we put an invalid discount, the program raises an `AssertionError`.
#
# A
"200% off" discount:
#
>>>
apply_discount(shoes, 2.0)
Traceback
(most recent call last):
File "", line 1, in
apply_discount(prod, 2.0)
File "", line 4, in
apply_discount
assert 0 <= price <=
product['price']
AssertionError
#
# A
"-30% off" discount:
#
>>>
apply_discount(shoes, -0.3)
Traceback
(most recent call last):
File "", line 1, in
apply_discount(prod, -0.3)
File "", line 4, in
apply_discount
assert 0 <= price <=
product['price']
AssertionError
|
Another example
|
Here, we
initially set the value of `x` to 1 and use `assert` to test the condition.
>>>
x = 1
>>>
assert x == 1
>>>
assert x == 2
Traceback
(most recent call last):
File "
AssertionError
>>>
|
No comments:
Post a Comment