python的异常处理一般做法,python异常处理

news/2024/7/5 5:46:52

在写python代码的过程中可能会出现一些错误,这些错误可区分为2类:语法错误 和 异常~

语法错误

>>> a = 2

>>> if a > 0 print('OK');

File "", line 1

if a > 0 print('OK');

^

SyntaxError: invalid syntax

如上语句即 存在语法错误,if 语句的条件后面没有冒号 ‘:’。

语法错误也称为解析错误,这类错误在程序执行之前就会被Python解释器检测到。如果使用IDE工具开发(例如 pycharm),pycharm会直接使用下标的红线提示开发者这里存在语法错误。这类错误必须在程序运行前就改正~

cc3765b5fa9f74daf23c6f7b7b1e39c8.png

异常

代码不存在语法错误,在运行过程中出现的逻辑错误,即为异常~

>>> 1 / 0

Traceback (most recent call last):

File "", line 1, in

ZeroDivisionError: division by zero

>>>

>>>

>>> lst = ['a', 'b', 'c']

>>> lst[2]

'c'

>>> lst[3]

Traceback (most recent call last):

File "", line 1, in

IndexError: list index out of range

程序在运行过程中,一旦发生异常,且发生的异常没有被捕获或者处理,则程序就会停止运行。

异常有不同的类型,在发生异常时,异常的类型及发生异常的原因 会被打印出来。上述示例中,第一个异常为 ZeroDivisionError(除数不能为0),第二个异常为 IndexError(列表指针超出范围)。

ZeroDivisionError 和 IndexError 都为Python的内置异常,即 python解释器 已经定义好的异常类型,常见的内置异常还有:StopIteration,GeneratorExit,AssertionError,EOFError,IOError,OSError等等。关于Python的内置异常及说明可参阅:https://docs.python.org/zh-cn/3.7/library/exceptions.html#bltin-exceptions

这些内置异常都继承于Exception类(自定义的异常一般也是直接或间接地继承自Exception类),且所有 内置异常的名称都存在于 内置名称空间中,可直接使用,而不需要 'import exceptions模块'。

异常处理

try...except... 语句

try...except... 语句用于捕获异常 及 对异常的处理。这样程序在发生异常时,可针对性的做出处理,避免程序的中断~,try...except... 语句的语法如下:

try:

可能发生异常的语句块

except [异常类型1]:

处理异常1的语句

except [异常类型2]:

处理异常2的语句

示例:

try:

a = 1/0

except ZeroDivisionError:

print('除数不能为0')

try...except... 语句的工作原理如下:

首先自上而下 执行 try 语句块中的代码(一般将可能发生异常的语句写在 try语句块 中)

如果没有发生异常,try语句块 中的代码执行完成后,将跳过 except语句块,继续向下执行

如果 try语句块 中有异常发生,则 try语句块 中剩下的代码将不会被执行。如果这个异常类型和 某一个 except 关键字后面的异常匹配,则执行这个 except 中的子句。

如果 try语句块 中出现的异常类型 和所有 except 关键字后面的异常都不匹配,则这个异常会被传递到外部的 try 语句中,如果外部没有做异常处理,程序将中断并打印错误信息~

若 try语句块 中除了 ZeroDivisionError 异常外,还存在别的异常:

try:

num = int(input("Enter a number: ")) # 这里可能会发生 ValueError 异常

a = 1/0

except ZeroDivisionError:

print('除数不能为0')

对于可能会先发生的 ValueError 异常,异常类型和 except 关键字后面的异常不匹配,那么这个 异常 将不会被 这个except 捕获,于是这个异常就会被传递到外部~,结果输出如下:

Enter a number: abc

Traceback (most recent call last):

File "...test.py", line 9, in

num = int(input("Enter a number: ")) # 这里可能会发生 ValueError

ValueError: invalid literal for int() with base 10: 'abc'

这个时候,可以使用多个 except 来捕获异常:

try:

num = int(input("Enter a number: ")) # 这里可能会发生 ValueError

a = 1/0

except ZeroDivisionError:

print('除数不能为0')

except ValueError:

print('请输入数字~')

# 结果输出:

Enter a number: abc

请输入数字~

当然也可以使用一个万能异常 Exception 来处理。由于内置异常和自定义异常都直接或间接地继承自 Exception,所以 Exception 可以用来匹配任何异常。这样做的优势在于 可以针对所有的异常统一进行捕获,缺点在于 不能针对指定的异常做出相应的处理,而是统一使用一种方式进行处理~

try:

num = int(input("Enter a number: "))

a = 1/0

except Exception:

pass

在实际的应用中,一般这两种方式会被结合使用:针对指定的那么几个异常分别进行捕获并做相应的处理,剩下的所有异常都统一使用 Exception 来捕获~

try:

f = open('myfile.txt')

s = f.readline()

i = int(s.strip())

except OSError as err:

print(err)

except ValueError:

print("数据类型无法转换")

except Exception:

print('Unexpected error')

最后的 Exception异常名 也可以省略不写(默认就是 Exception )

except:

print('Unexpected error')

as 获取异常信息

异常发生时,都会有关于这个异常的具体描述信息,异常的描述信息可通过 as 关键字获取,这个在上述示例中已经有使用~

try:

f = open('myfile.txt')

s = f.readline()

i = int(s.strip())

except OSError as err:

print(err)

# 若文件不存在,或有如下输出:

[Errno 2] No such file or directory: 'myfile.txt'

try...except...else... 语句

else 为可选字句,放在 except 字句后面,若 try 语句块中没有异常发生,则会执行else 语句块中的代码~

try:

f = open('myfile.txt')

s = f.readline()

i = int(s.strip())

except OSError as err:

print(err)

else:

f.close() # try 语句块正常执行完成后,关闭打开的文件

try...except...finally... 语句

finally 也为可选字句,放在所有语句块的最后。不管 try 语句块中是否触发异常,都会执行 finally 语句块中的代码。finally 语句块中的代码一般都用于 关闭系统资源,例如关闭文件,关闭数据库连接等~

def connDB():

try:

conn = pymysql.connect(host=HOST, user=USER, password=PASSWD, database=DATEBASE, charset='utf8', cursorclass=pymysql.cursors.DictCursor)

return conn

except Exception:

logger.error("can not connect to database!")

exit()

db = connDB()

try:

...

pass

except:

...

pass

finally:

db.close()

在操作文件时,还可以使用 with...as... 语句来自动关闭文件,即不管 with语句块 中是否触发异常,with语句块执行完毕后都会自动关闭文件~

try:

f = open('myfile.txt', mode='r')

a = 1/0

except Exception:

print(f.closed) # False,当 try语句块中发生异常,文件没有被关闭

##############

try:

with open('myfile.txt', mode='r') as f:

a = 1 / 0

except Exception:

print(f.closed) # True,文件已经自动关闭

raise触发异常

raise语句用于手动触发异常,触发的异常可以通过传递参数说明异常的原因,例如:

>>> raise IndexError('lst out of range')

Traceback (most recent call last):

File "", line 1, in

IndexError: lst out of range

在 except语句块中,若不想对捕获的异常进行处理,则可以使用 raise语句 重新触发异常,由外层的 try语句来进行处理~

try:

raise ZeroDivisionError('abc')

except ZeroDivisionError:

print('除数为0')

raise # 更简单的写法,重新触发捕获到的异常

assert 语句

assert语法:

assert expression

assert 关键字根据后面的表达式的真假来确定程序是否继续往下执行。若表达式返回为True,则程序继续往下执行,若为False,则触发 AssertionError 异常~

print('start...')

assert 1 == 1

print('end...')

# 输出结果:

start...

end...

################

print('start...')

assert 1 == 2

print('end...')

# 输出结果:

start...

Traceback (most recent call last):

File ".../test.py", line 17, in

assert 1 == 2

AssertionError

自定义异常

通过继承 Exception 类来创建自定义的异常;自定义异常应该尽量保持异常类的简单,一般自定义异常仅用于提取特有的错误信息~。自定义异常示例如下:

class MyError(Exception):

def __init__(self, ErrorInfo):

Exception.__init__(self)

self.errorinfo=ErrorInfo

def __str__(self):

return self.errorinfo

注意:自定义的异常类只能通过 raise关键字 来手动触发。

traceback追踪异常

使用 traceback 关键字追踪异常,需要导入 traceback 模块(import traceback)。

import traceback

try:

f = open('myfile.txt', mode='r')

a = 1/0

except Exception:

traceback.print_exc()

logger.error(traceback.format_exc()) #使用日志模块记录 异常的详细信息,或使用 traceback.print_exc(file=path) 记录到指定文件

# 输出信息如下:

Traceback (most recent call last):

File "/Users/luyi/PycharmProjects/untitled/day26/test.py", line 12, in

a = 1/0

ZeroDivisionError: division by zero

这里异常信息的输出和不捕获异常时候系统的输出一致,其实 traceback.print_exc() 函数调用了sys.exc_info() 函数来完成 异常信息的输出,traceback.print_exc()的源码如下:

def print_exc(limit=None, file=None):

"""Shorthand for 'print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback, limit, file)'.

(In fact, it uses sys.exc_info() to retrieve the same information

in a thread-safe way.)"""

if file is None:

file = sys.stderr

try:

etype, value, tb = sys.exc_info() # 调用了 sys.exc_info() 函数

print_exception(etype, value, tb, limit, file)

finally:

etype = value = tb = None

.................^_^


http://www.niftyadmin.cn/n/3660235.html

相关文章

最近工作进展了一小步....

本来文章标题为: "发生在7 月1日前夕的一件事,目前知道的人不多"...不过后来太过标题党,所以改成纯枪稿.7月1日 ZDNet China 软件频道新版首页上线啦!直接去新首页瞅瞅 :新首页--> http://soft.zdnet.com.cnZDNet China 软件频道,是ZDNet China面向企业…

php一课一文,php基础,php学习第一课

Php基础一、什么是PHPPhp外文名:Hypertext Preprocessor是一种服务器端运行的开源的脚本语言,如果您有C语言的基础,学习起来轻而易举!二、PHP的运行环境是什么PHP的运行环境推荐使用的有三种服务器环境,别的建议大家就不要考虑了&…

php echars 数据库,新建数据库 · Echarts+tp5框架,实现数据可视化实例 · 看云

## phpstudy 安装:#### 1. 请点击此处下载http://www.phpstudy.net/download.html#### 2. 根目录:D:\phpStudy\WWW#### 3. 把TP5框架文件,放到根目录下面,并将文件夹名字重命名为test。![](https://box.kancloud.cn/00dd82492e715…

jquery怎么写php代码,15.2.3 构建PHP代码及jQuery代码(2)

15.2.3 构建PHP代码及jQuery代码(2)下面需要对从客户端以POST形式发送过来的数据进行处理,代码如下所示:foreach($_POST as $key>$value){$$keymysql_real_escape_string($value);}注意,这里使用了一个循环来处理POST信息中的各个参数&am…

[大图]Linux family tree“族谱”大串烧

最近看到网上有人晒Linux家族树,所以到网上搜了一下,还真有斩获。大图描绘了从91年Linux的鼻祖GNU/Linux开始一直到2006年的各个Liunx家族的“父子”关系。主流的发行版本Debian,SuSE,RedHat,到Ubuntu。其中在01,02年间和微软Windows因为命名…

oracle批量数据修改数据类型,oracle如何批量修改字段中的数据

oracle如何批量修改字段中的数据以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!date是Oracle保留字,居然拿来作字段名。假设这是一个文本字段,字段名为dataupdate t1…

oracle亚太,Oracle亚太研发中心招聘职位

地点在深圳,职位是:(Senior) Member of Technical StaffProduct DevelopmentWho are we?ST Testing is the first team in Oracle Asia R&D Center Shenzhen. Right now, we have about172 people, all of them are graduated from the top univers…

oracle 函数 指针参数传递,C++中用指向数组的指针作函数参数

1.一维数组名作为函数参数传递一位数组名,就相当于该数组的首个元素的地址;int a[10];int *p;pa;//pa与p&a[0]是等价的实例代码:#includeusing namespace std;int main(){int a[10]{1,2,3,4,5,6,7,8,9,10};void Print(int *p ,int n);Pri…