5 篇文章

# 盘一盘 Python 系列特别篇 - 异常处理

0

1. try-except
2. try-except-else
3. try-except-else-finally
4. 抛出 Exception
5. 总结

1

Try-Except

1. 知道错误但不确定类型，用 except Exception
2. 知道错误而且确定类型，用 except some_exception
3. 知道错误而且有多个错误
• 用多个 except
• 用 except (exc_1, exc_2, ... exc_n)

1.1

``````def divide(a, b):
try:
c = a / b
print(f"Result = {c:.4f}.")
except:
print('Divisor is zero and division is impossible!')``````
``divide(10, 3)``
``Result = 3.3333.``
``divide(10, 0)``
``Divisor is zero and division is impossible!``

• 10 除以 3 ，程序正常运行
• 10 除以 0 ，异常被 except 语句下处理，输出有用的信息

1.2

``10/0``
``````---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-4-e574edb36883> in <module>
----> 1 10/0

ZeroDivisionError: division by zero``````

``````def divide(a, b):
try:
c = a / b
print(f"Result = {c:.4f}.")
except ZeroDivisionError:
print('Divisor is zero and division is impossible!')``````
``divide(10, 0)``
``Divisor is zero and division is impossible!``

``````def divide(a, b):
try:
c = a / b
d = cc + 1
print(f"Result = {c:.4f}.")
except ZeroDivisionError:
print('Divisor is zero and division is impossible!')``````
``divide(10, 2)``
``````---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-8-15fa568ba405> in <module>
----> 1 divide(10, 2)

<ipython-input-7-97d83e2f78ac> in divide(a, b)
2     try:
3         c = a / b
----> 4 d = cc + 1
5         print(f"Result = {c:.4f}.")
6     except ZeroDivisionError:

NameError: name 'cc' is not defined``````

``````def divide(a, b):
try:
c = a / b
d = cc + 1
print(f"Result = {c:.4f}.")
except ZeroDivisionError:
print('Divisor is zero and division is impossible！')
except Exception:
print('Something wrong！')``````
``divide(10, 0)``
``Divisor is zero and division is impossible！``
``divide(10, 2)``
``Something wrong！``

1.3

``````def divide(a, b):
try:
c = a / b
d = cc + 1
print(f"Result = {c:.4f}.")
except ZeroDivisionError:
print('Divisor is zero and division is impossible!')
except NameError:
print('Some variable name is undefined！')``````
``divide(10, 2)``
``Some variable name is undefined！``
``divide(10, 0)``
``Divisor is zero and division is impossible!``

• 如果 a 是浮点型变量 1.3 或者字符型变量 '1031'，程序运行正常。
• 如果 a 是这种字符型变量 '1 mio'，会报 ValueError 的错误。
• 如果 a 是列表型变量 [1, 2]，会报 TypeError 的错误（这对元组、字典、集合都适用）。
``````def convert_to_int(a):
try:
int_value = int(a)
print('The converted integer is', int_value)
except ValueError:
print("'a' is not a numerical value or expression.")
except TypeError:
print("The type of 'a' is not compatiable.")``````

``convert_to_int(1.3)``
``The converted integer is 1``
``convert_to_int('1031')``
``The converted integer is 1031``

``convert_to_int('1 mio')``
``'a' is not a numerical value or expression.``

``convert_to_int([1, 2])``
``The type of 'a' is not compatiable.``

except exc_1:

except exc_2:

...

except exc_n:

=

except (exc_1, exc_2, ... exc_n)

``````def convert_to_int(a):
try:
int_value = int(a)
print('The converted integer is', int_value)
except (ValueError, TypeError):
print("Error occurred. Either 'a' is a numerical value " \
"or expression or type of 'a' is incompatible.")``````

``convert_to_int('1 mio')``
``Error occurred. Either 'a' is a numerical value or expression or type of 'a' is incompatible.``
``convert_to_int([1, 2])``
``Error occurred. Either 'a' is a numerical value or expression or type of 'a' is incompatible.``

• 如果要根据要处理的异常执行不同的代码，可以采用第一种范式，根据不同异常输出更明确的信息。
• 如果要为所有要处理的异常执行同一段代码，可以采用第二种范式，因为它避免了多个 except 子句中的重复代码。

except (exp_1, ... exp_n) as err

``````def convert_to_int(a):
try:
int_value = int(a)
print('The converted integer is', int_value)
except (ValueError, TypeError) as err:
print('GOT ERROR WITH MESSAGE: {0}'.format(err.args[0]))``````
``convert_to_int('1 mio')``
``GOT ERROR WITH MESSAGE: invalid literal for int() with base 10: '1 mio'``
``convert_to_int([1, 2])``
``GOT ERROR WITH MESSAGE: int() argument must be a string, a bytes-like object or a number, not 'list'``

2

Try-Except-Else

• 当 try 语句下的代码未发生异常时，才会执行 else 子句下的代码。
• 当 try 语句下的代码中发生异常，则 except 语句将处理异常，else 语句将不会执行。

``````def divide(a, b):
try:
c = a / b
except ZeroDivisionError:
print('Divisor is zero and division is impossible!')
else:
print(f"Result = {c:.4f}.")``````
``divide(10, 2)``
``Result = 5.0000.``
``divide(10, 0)``
``Divisor is zero and division is impossible!``

3

Try-Except-Else-Finally

``````def divide(a, b):
try:
c = a / b
except ZeroDivisionError:
print('Divisor is zero and division is impossible!')
else:
print(f"Result = {c:.4f}.")
finally:
print('Error or no error, FINALLY DONE!')``````

``divide(10, 0)``
``````Divisor is zero and division is impossible!
Error or no error, FINALLY DONE!``````

``divide(10, 2)``
``````Result = 5.0000.
Error or no error, FINALLY DONE!``````

``divide(10, '2')``
``````Error or no error, FINALLY DONE!

---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-51-ae7e5f3b4399> in <module>
----> 1 divide(10, '2')

<ipython-input-48-ef792bab0247> in divide(a, b)
1 def divide(a, b):
2     try:
----> 3 c = a / b
4     except ZeroDivisionError:
5         print('Divisor is zero and division is impossible!')

TypeError: unsupported operand type(s) for /: 'int' and 'str'``````

``````def divide(a, b):
try:
c = a / b
except ZeroDivisionError:
print('Divisor is zero and division is impossible!')
except Exception:
print('Something wrong!')
else:
print(f"Result = {c:.4f}.")
finally:
print('Error or no error, FINALLY DONE!')``````
``divide(10, '2')``
``````Something wrong!
Error or no error, FINALLY DONE!``````

``````finish_task = False

try:
inputFileName = input("输入要读取的文件名 (txt 格式): ")
inputFileName = inputFileName + ".txt"
inputFile = open(inputFileName, "r")
except IOError:
print("\n文件", inputFileName, "不能被打开")
except Exception:
print("\n有不明错误")
else:
print("\n正在打开文件", inputFileName, "\n")

for line in inputFile:
print(line, end="")

print("\n\n完成读取文件", inputFileName)
finally:
inputFile.close()
print("\n关闭文件", inputFileName)
else:
print("\n未能完成读取文件", inputFileName)``````

``````输入要读取的文件名 (txt 格式): asf

``````输入要读取的文件名 (txt 格式): Error

Errors or mistakes in a program are often referred to as bugs. They are almost always the fault of the programmer. The process of finding and eliminating errors is called debugging. Errors can be classified into three major groups:

I. Syntax errors
II. Runtime errors
III. Logical errors

4

Raise Exception

• 抛出 Python 里内置的异常
• 抛出我们自定义的异常

``````try:
a = int(input("Enter a positive integer: "))
if a <= 0:
raise ValueError("That is not a positive number!")
except ValueError as err:
print(err)``````

• 如果昨天和今天的价值都小于零，我们抛出 ValueError 并带着 "Negative worth!" 的信息。
• 如果组合增值小于零，我们也抛出 ValueError 并带着 "Negative return!" 的信息。

``````def portfolio_value(last_worth, current_worth):
if last_worth < 0 or current_worth < 0:
raise ValueError('Negative worth!')
value = current_worth - last_worth
if value < 0:
raise ValueError('Negative return!')``````

``````try:
portfolio_value(-10000, 10001)
except ValueError as err:
print(err)``````
``Negative worth!``
``````try:
portfolio_value(10000, 9999)
except ValueError as err:
print(err)``````
``Negative return!``

class Error(Exception):

class your_exception(Error):

``````class Error(Exception):
pass

class NegativePortfolioValueWarning(Error):
def __init__(self, expression, message):
self.expression = expression
self.message = message``````

``````def portfolio_value(last_worth, current_worth):
if last_worth < 0 or current_worth < 0:
raise ValueError('Negative worth!')
value = current_worth - last_worth
if value < 0:
raise NegativePortfolioValueWarning(
'NegativePortfolioValueWarning', \
'Negative return. Take a look!')``````

``````try:
portfolio_value(-10000, 10001)
except ValueError as err:
print(err)
except NegativePortfolioValueWarning as err:
print('[', err.args[0], '] -', err.args[1])``````
``Negative worth!``
``````try:
portfolio_value(10000, 9999)
except ValueError as err:
print(err)
except NegativePortfolioValueWarning as err:
print('[', err.args[0], '] -', err.args[1]``````
``[ NegativePortfolioValueWarning ] - Negative return. Take a look!``

5

Stay Tuned！