python教程13、异常处理(__import__, hasatter,getatter,setatter)
一、异常处理
python异常:
python的运行时错误称作异常
(1)语法错误:软件的结构上有错误而导致不能被解释器解释或不能被编译器编译
(2)逻辑错误:由于不完整或不合法的输入所致,也可能是逻辑无法生成、计算或者输出结果需要的过程无法执行等
python异常是一个对象,表示错误或意外情况
(1)在python检测到一个错误时,将触发一个异常
python可以通常异常传导机制传递一个异常对象,发出一个异常情况出现的信号
程序员也可以在代码中手动触发异常
(2)python异常也可以理解为:程序出现了错误而在正常控制流以外采取的行为
第一阶段:解释器触发异常,此时当前程序流将被打断
第二阶段:异常处理,如忽略非致命错误、减轻错误带来的影响等
检测和处理异常:
(1)异常通过try语句来检测
任何在try语句块里的代码都会被检测,以检查有无异常发生
(2)try语句主要有两种形式:
try-except: 检测和处理异常
可以有多个except
支持使用else子句处理没有探测异常的执行的代码
try-finally: 仅检查异常并做一些必要的清理工作
仅能有一个finally
(3)try语句的复合形式:
try-execpt-else-finally
1、异常基础
在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!!
1
2
3
4
|
try : pass except Exception as ex: pass |
#python3.x中是这么写的,python2.x是这么写的: except Exception,e:
需求:将用户输入的两个数字相加
while True: num1 = raw_input('num1:') num2 = raw_input('num2:') try: num1 = int(num1) num2 = int(num2) result = num1 + num2 except Exception as e: print('出现异常,信息如下:') print(e)
2、异常种类
python中的异常种类非常多,每个异常专门用于处理某一项异常!!!
AssertionError: 断言语句失败 AttributeError: 属性引用或赋值失败 FloatingPointError: 浮点型运算失败 IOError: I/O操作失败 ImportError: import语句不能找到要导入的模块,或者不能找到该模块特别请求的名称 IndentationError: 解析器遇到了一个由于错误的缩进而引发的语法错误 IndexError: 用来索引序列的证书超出了范围 KeyError: 用来索引映射的键不再映射中 keyboardInterrupt: 用户按了中断键(Ctrl+c,Ctrl+Break或Delete键) MemoryError: 运算耗尽内存 NameError: 引用了一个不存在的变量名 NotImplementedError: 由抽象基类引发的异常,用于指示一个具体的子类必须覆盖一个方法 OSError: 由模块os中的函数引发的异常,用来指示平台相关的错误 OverflowError: 整数运算的结果太大导致溢出 SyntaxError: 语法错误 SystemError: python本身或某些扩展模块中的内部错误 TypeError:对某对象执行了不支持的操作 UnboundLocalError:引用未绑定值的本地变量 UnicodeError:在Unicode的字符串之间进行转换时发生的错误 ValueError:应用于某个对象的操作或函数,这个对象具有正确的类型,但确有不适当的值 WindowsError:模块os中的函数引发的异常,用来指示与WIndows相关的错误 ZeroDivisionError: 除数为0
实例:IndexError
dic = ["python", 'linux'] try: dic[10] except IndexError as e: print(e)
实例:KeyError
dic = {'k1':'v1'} try: dic['k20'] except KeyError as e: print(e)
对于上述实例,异常类只能用来处理指定的异常情况,如果非指定异常则无法处理。
1
2
3
4
5
6
7
|
# 未捕获到异常,程序直接报错 s1 = 'hello' try : int (s1) except IndexError as e: print (e) |
所以,写程序时需要考虑到try代码块中可能出现的任意异常,可以这样写:
1
2
3
4
5
6
7
8
9
|
s1 = 'hello' try : int (s1) except IndexError as e: print (e) except KeyError as e: print (e) except ValueError as e: print (e) |
万能异常 在python的异常中,有一个万能异常:Exception,他可以捕获任意异常,即:
1
2
3
4
5
|
s1 = 'hello' try : int (s1) except Exception as e: print (e) |
接下来你可能要问了,既然有这个万能异常,其他异常是不是就可以忽略了!
答:当然不是,对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行
1
2
3
4
5
6
7
8
9
|
s1 = 'hello' try : int (s1) except KeyError as e: print ( '键错误' ) except IndexError as e: print ( '索引错误' ) except Exception as e: print ( '错误' ) |
3、异常其他结构
1
2
3
4
5
6
7
8
9
10
11
12
|
try : # 主代码块 pass except KeyError as e: # 异常时,执行该块 pass else : # 主代码块执行完,执行该块 pass finally : # 无论异常与否,最终执行该块 pass |
4、主动触发异常
1
2
3
4
|
try : raise Exception( '错误了。。。' ) except Exception as e: print (e) |
5、自定义异常
1
2
3
4
5
6
7
8
9
10
11
12
|
class MyException(Exception): def __init__( self , msg): self .message = msg def __str__( self ): return self .message try : raise MyException( '我的异常' ) except WupeiqiException as e: print (e) |
6、断言
1
2
3
4
5
|
# assert 条件 assert 1 = = 1 assert 1 = = 2 |
二、反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr、__import__(module_name),改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员、导入模块以字符串方式导入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class Foo( object ): def __init__( self ): self .name = 'python' def func( self ): return 'func' obj = Foo() # #### 检查是否含有成员 #### hasattr (obj, 'name' ) hasattr (obj, 'func' ) # #### 获取成员 #### getattr (obj, 'name' ) getattr (obj, 'func' ) # #### 设置成员 #### setattr (obj, 'age' , 18 ) setattr (obj, 'show' , lambda num: num + 1 ) # #### 删除成员 #### delattr (obj, 'name' ) delattr (obj, 'func' ) |
详细解析:
当我们要访问一个对象的成员时,应该是这样操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Foo( object ): def __init__( self ): self .name = 'python' def func( self ): return 'func' obj = Foo() # 访问字段 obj.name # 执行方法 obj.func() |
class Foo(object): def __init__(self): self.name = 'python' # 不允许使用 obj.name obj = Foo()
答:有两种方式,如下:
class Foo(object): def __init__(self): self.name = 'python' def func(self): return 'func' # 不允许使用 obj.name obj = Foo() print obj.__dict__['name']
第二种:
class Foo(object): def __init__(self): self.name = 'python' def func(self): return 'func' # 不允许使用 obj.name obj = Foo() print getattr(obj, 'name')
d、比较三种访问方式
- obj.name
- obj.__dict__['name']
- getattr(obj, 'name')
答:第一种和其他种比,...
第二种和第三种比,...
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server class Handler(object): def index(self): return 'index' def news(self): return 'news' def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) url = environ['PATH_INFO'] temp = url.split('/')[1] obj = Handler() is_exist = hasattr(obj, temp) if is_exist: func = getattr(obj, temp) ret = func() return ret else: return '404 not found' if __name__ == '__main__': httpd = make_server('', 8001, RunServer) print "Serving HTTP on port 8000..." httpd.serve_forever()
结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!
类也是对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Foo( object ): staticField = "old boy" def __init__( self ): self .name = 'wupeiqi' def func( self ): return 'func' @staticmethod def bar(): return 'bar' print getattr (Foo, 'staticField' ) print getattr (Foo, 'func' ) print getattr (Foo, 'bar' ) |
模块也是对象
home.py
#!/usr/bin/env python # -*- coding:utf-8 -*- def dev(): return 'dev'
index.py
#!/usr/bin/env python # -*- coding:utf-8 -*- """ 程序目录: home.py index.py 当前文件: index.py """ import home as obj #obj.dev() func = getattr(obj, 'dev') func()
两个例子:
第一个例子:模块和主程序在同一目录
home.py
#!/usr/bin/env python # -*- coding:utf-8 -*- def index(): print("炫酷的主页面")
index.py
#!/usr/bin/env python # -*- coding:utf-8 -*- # 反射:基于字符串的形式去对象(模块)中操作其成员getattr(),setattr(),hasattr(),delattr() # 扩展:导入模块 # import xxx # from xxx import ooo # # obj = __import__("xxx") # obj = __import__("xxx." + ooo,fromlist=True) def run(): while True: inp = input("请输入要访问的URL:") mo,fn = inp.split('/') obj = __import__(mo) if hasattr(obj,fn): func = getattr(obj,fn) func() else: print("网页不存在") run()
执行的时候输入URL:home/index 这样就执行了home模块下的index函数
第二个例子:模块和主程序不在同一目录
lib/account.py
#!/usr/bin/env python # -*- coding:utf-8 -*- def login(): print("炫酷的登录页面") def logout(): print("炫酷的退出页面")
index1.py
#!/usr/bin/env python # -*- coding:utf-8 -*- # 反射:基于字符串的形式去对象(模块)中操作其成员getattr(),setattr(),hasattr(),delattr() # 扩展:导入模块 # import xxx # from xxx import ooo # # obj = __import__("xxx") # obj = __import__("xxx." + ooo,fromlist=True) def run(): while True: inp = input("请输入要访问的URL:") mo,fn = inp.split('/') obj = __import__("lib." + mo,fromlist=True) if hasattr(obj,fn): func = getattr(obj,fn) func() else: print("网页不存在") run()
执行的时候输入URL:account/login 这样就执行了lib/account下的login函数
### 另外一种实现方式
index2.py
1
2
3
4
5
6
7
8
|
import importlib module = "lib.account" func_name = "login" m = importlib.import_module(module) func = getattr (m, func_name) func() |