Python自动化运维之13、异常处理及反射(__import__,getattr,hasattr,setattr)
一、異常處理
python異常:
python的運(yùn)行時(shí)錯(cuò)誤稱(chēng)作異常
(1)語(yǔ)法錯(cuò)誤:軟件的結(jié)構(gòu)上有錯(cuò)誤而導(dǎo)致不能被解釋器解釋或不能被編譯器編譯
(2)邏輯錯(cuò)誤:由于不完整或不合法的輸入所致,也可能是邏輯無(wú)法生成、計(jì)算或者輸出結(jié)果需要的過(guò)程無(wú)法執(zhí)行等
python異常是一個(gè)對(duì)象,表示錯(cuò)誤或意外情況
(1)在python檢測(cè)到一個(gè)錯(cuò)誤時(shí),將觸發(fā)一個(gè)異常
python可以通常異常傳導(dǎo)機(jī)制傳遞一個(gè)異常對(duì)象,發(fā)出一個(gè)異常情況出現(xiàn)的信號(hào)
程序員也可以在代碼中手動(dòng)觸發(fā)異常
(2)python異常也可以理解為:程序出現(xiàn)了錯(cuò)誤而在正常控制流以外采取的行為
第一階段:解釋器觸發(fā)異常,此時(shí)當(dāng)前程序流將被打斷
第二階段:異常處理,如忽略非致命錯(cuò)誤、減輕錯(cuò)誤帶來(lái)的影響等
檢測(cè)和處理異常:
(1)異常通過(guò)try語(yǔ)句來(lái)檢測(cè)
任何在try語(yǔ)句塊里的代碼都會(huì)被檢測(cè),以檢查有無(wú)異常發(fā)生
(2)try語(yǔ)句主要有兩種形式:
try-except: 檢測(cè)和處理異常
可以有多個(gè)except
支持使用else子句處理沒(méi)有探測(cè)異常的執(zhí)行的代碼
try-finally: 僅檢查異常并做一些必要的清理工作
僅能有一個(gè)finally
(3)try語(yǔ)句的復(fù)合形式:
try-execpt-else-finally
?
1、異常基礎(chǔ)
在編程過(guò)程中為了增加友好性,在程序出現(xiàn)bug時(shí)一般不會(huì)將錯(cuò)誤信息顯示給用戶,而是現(xiàn)實(shí)一個(gè)提示的頁(yè)面,通俗來(lái)說(shuō)就是不讓用戶看見(jiàn)大黃頁(yè)!!!
try:pass except Exception as ex: pass#python3.x中是這么寫(xiě)的,python2.x是這么寫(xiě)的: ?except Exception,e:
需求:將用戶輸入的兩個(gè)數(shù)字相加
while True:num1 = raw_input('num1:')num2 = raw_input('num2:')try:num1 = int(num1)num2 = int(num2)result = num1 + num2except Exception as e:print('出現(xiàn)異常,信息如下:')print(e)2、異常種類(lèi)
python中的異常種類(lèi)非常多,每個(gè)異常專(zhuān)門(mén)用于處理某一項(xiàng)異常!!!
AssertionError: 斷言語(yǔ)句失敗 AttributeError: 屬性引用或賦值失敗 FloatingPointError: 浮點(diǎn)型運(yùn)算失敗 IOError: I/O操作失敗 ImportError: import語(yǔ)句不能找到要導(dǎo)入的模塊,或者不能找到該模塊特別請(qǐng)求的名稱(chēng) IndentationError: 解析器遇到了一個(gè)由于錯(cuò)誤的縮進(jìn)而引發(fā)的語(yǔ)法錯(cuò)誤 IndexError: 用來(lái)索引序列的證書(shū)超出了范圍 KeyError: 用來(lái)索引映射的鍵不再映射中 keyboardInterrupt: 用戶按了中斷鍵(Ctrl+c,Ctrl+Break或Delete鍵) MemoryError: 運(yùn)算耗盡內(nèi)存 NameError: 引用了一個(gè)不存在的變量名 NotImplementedError: 由抽象基類(lèi)引發(fā)的異常,用于指示一個(gè)具體的子類(lèi)必須覆蓋一個(gè)方法 OSError: 由模塊os中的函數(shù)引發(fā)的異常,用來(lái)指示平臺(tái)相關(guān)的錯(cuò)誤 OverflowError: 整數(shù)運(yùn)算的結(jié)果太大導(dǎo)致溢出 SyntaxError: 語(yǔ)法錯(cuò)誤 SystemError: python本身或某些擴(kuò)展模塊中的內(nèi)部錯(cuò)誤 TypeError:對(duì)某對(duì)象執(zhí)行了不支持的操作 UnboundLocalError:引用未綁定值的本地變量 UnicodeError:在Unicode的字符串之間進(jìn)行轉(zhuǎn)換時(shí)發(fā)生的錯(cuò)誤 ValueError:應(yīng)用于某個(gè)對(duì)象的操作或函數(shù),這個(gè)對(duì)象具有正確的類(lèi)型,但確有不適當(dāng)?shù)闹?WindowsError:模塊os中的函數(shù)引發(fā)的異常,用來(lái)指示與WIndows相關(guān)的錯(cuò)誤 ZeroDivisionError: 除數(shù)為0 ArithmeticError AssertionError AttributeError BaseException BufferError BytesWarning DeprecationWarning EnvironmentError EOFError Exception FloatingPointError FutureWarning GeneratorExit ImportError ImportWarning IndentationError IndexError IOError KeyboardInterrupt KeyError LookupError MemoryError NameError NotImplementedError OSError OverflowError PendingDeprecationWarning ReferenceError RuntimeError RuntimeWarning StandardError StopIteration SyntaxError SyntaxWarning SystemError SystemExit TabError TypeError UnboundLocalError UnicodeDecodeError UnicodeEncodeError UnicodeError UnicodeTranslateError UnicodeWarning UserWarning ValueError Warning ZeroDivisionError 更多異常實(shí)例:IndexError
dic = ["python", 'linux'] try:dic[10] except IndexError as e:print(e)實(shí)例:KeyError
dic = {'k1':'v1'} try:dic['k20'] except KeyError as e:print(e)對(duì)于上述實(shí)例,異常類(lèi)只能用來(lái)處理指定的異常情況,如果非指定異常則無(wú)法處理。
# 未捕獲到異常,程序直接報(bào)錯(cuò)s1 = 'hello' try:int(s1) except IndexError as e:print(e)所以,寫(xiě)程序時(shí)需要考慮到try代碼塊中可能出現(xiàn)的任意異常,可以這樣寫(xiě):
s1 = 'hello' try:int(s1) except IndexError as e:print(e) except KeyError as e:print(e) except ValueError as e:print(e)萬(wàn)能異常 在python的異常中,有一個(gè)萬(wàn)能異常:Exception,他可以捕獲任意異常,即:
s1 = 'hello' try:int(s1) except Exception as e:print(e)接下來(lái)你可能要問(wèn)了,既然有這個(gè)萬(wàn)能異常,其他異常是不是就可以忽略了!
答:當(dāng)然不是,對(duì)于特殊處理或提醒的異常需要先定義,最后定義Exception來(lái)確保程序正常運(yùn)行
s1 = 'hello' try:int(s1) except KeyError as e:print('鍵錯(cuò)誤') except IndexError as e:print('索引錯(cuò)誤') except Exception as e:print('錯(cuò)誤')3、異常其他結(jié)構(gòu)
try:# 主代碼塊pass except KeyError as e:# 異常時(shí),執(zhí)行該塊pass else:# 主代碼塊執(zhí)行完,執(zhí)行該塊pass finally:# 無(wú)論異常與否,最終執(zhí)行該塊pass4、主動(dòng)觸發(fā)異常
try:raise Exception('錯(cuò)誤了。。。') except Exception as e:print(e)5、自定義異常
class MyException(Exception):def __init__(self, msg):self.message = msgdef __str__(self):return self.messagetry:raise MyException('我的異常') except WupeiqiException as e:print(e)6、斷言
# assert 條件assert 1 == 1assert 1 == 2二、反射
python中的反射功能是由以下四個(gè)內(nèi)置函數(shù)提供:hasattr、getattr、setattr、delattr、__import__(module_name)、importlib,改五個(gè)函數(shù)分別用于對(duì)對(duì)象內(nèi)部執(zhí)行:檢查是否含有某成員、獲取成員、設(shè)置成員、刪除成員、導(dǎo)入模塊以字符串方式導(dǎo)入。
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')# #### 設(shè)置成員 #### setattr(obj, 'age', 18) setattr(obj, 'show', lambda num: num + 1)# #### 刪除成員 #### delattr(obj, 'name') delattr(obj, 'func')詳細(xì)解析:
當(dāng)我們要訪問(wèn)一個(gè)對(duì)象的成員時(shí),應(yīng)該是這樣操作:
class Foo(object):def __init__(self):self.name = 'python'def func(self):return 'func'obj = Foo()# 訪問(wèn)字段 obj.name # 執(zhí)行方法 obj.func() 那么問(wèn)題來(lái)了? a、上述訪問(wèn)對(duì)象成員的 name 和 func 是什么?? 答:是變量名 b、obj.xxx 是什么意思?? 答:obj.xxx 表示去obj中或類(lèi)中尋找變量名 xxx,并獲取對(duì)應(yīng)內(nèi)存地址中的內(nèi)容。 c、需求:請(qǐng)使用其他方式獲取obj對(duì)象中的name變量指向內(nèi)存中的值 “python” 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、比較三種訪問(wèn)方式
- obj.name
- obj.__dict__['name']
- getattr(obj, 'name')
答:第一種和其他種比,...
? ? ? 第二種和第三種比,...
結(jié)論:反射是通過(guò)字符串的形式操作對(duì)象相關(guān)的成員。一切事物都是對(duì)象!!!
類(lèi)也是對(duì)象
class Foo(object):staticField = "old boy"def __init__(self):self.name = 'wupeiqi'def func(self):return 'func'@staticmethoddef bar():return 'bar'print getattr(Foo, 'staticField') print getattr(Foo, 'func') print getattr(Foo, 'bar')模塊也是對(duì)象
home.py
#!/usr/bin/env python # -*- coding:utf-8 -*-def dev():return 'dev'?index.py
#!/usr/bin/env python # -*- coding:utf-8 -*-""" 程序目錄:home.pyindex.py當(dāng)前文件:index.py """import home as obj#obj.dev() func = getattr(obj, 'dev') func()兩個(gè)例子:
第一個(gè)例子:模塊和主程序在同一目錄
home.py
#!/usr/bin/env python # -*- coding:utf-8 -*-def index():print("炫酷的主頁(yè)面")index.py
#!/usr/bin/env python # -*- coding:utf-8 -*- # 反射:基于字符串的形式去對(duì)象(模塊)中操作其成員getattr(),setattr(),hasattr(),delattr() # 擴(kuò)展:導(dǎo)入模塊 # import xxx # from xxx import ooo # # obj = __import__("xxx") # obj = __import__("xxx." + ooo,fromlist=True)def run():while True:inp = input("請(qǐng)輸入要訪問(wèn)的URL:")mo,fn = inp.split('/')obj = __import__(mo)if hasattr(obj,fn):func = getattr(obj,fn)func()else:print("網(wǎng)頁(yè)不存在")run()執(zhí)行的時(shí)候輸入U(xiǎn)RL:home/index ? 這樣就執(zhí)行了home模塊下的index函數(shù)
第二個(gè)例子:模塊和主程序不在同一目錄
lib/account.py
#!/usr/bin/env python # -*- coding:utf-8 -*-def login():print("炫酷的登錄頁(yè)面")def logout():print("炫酷的退出頁(yè)面")index1.py
#!/usr/bin/env python # -*- coding:utf-8 -*-# 反射:基于字符串的形式去對(duì)象(模塊)中操作其成員getattr(),setattr(),hasattr(),delattr() # 擴(kuò)展:導(dǎo)入模塊 # import xxx # from xxx import ooo # # obj = __import__("xxx") # obj = __import__("xxx." + ooo,fromlist=True)def run():while True:inp = input("請(qǐng)輸入要訪問(wèn)的URL:")mo,fn = inp.split('/')obj = __import__("lib." + mo,fromlist=True)if hasattr(obj,fn):func = getattr(obj,fn)func()else:print("網(wǎng)頁(yè)不存在")run()執(zhí)行的時(shí)候輸入U(xiǎn)RL:account/login 這樣就執(zhí)行了lib/account下的login函數(shù)
?
###?另外一種實(shí)現(xiàn)方式
index2.py
import importlibmodule = "lib.account" func_name = "login"m = importlib.import_module(module) func = getattr(m, func_name) func()
利用反射和super()的一個(gè)例子:點(diǎn)這里
轉(zhuǎn)載于:https://www.cnblogs.com/xiaozhiqi/p/5778856.html
總結(jié)
以上是生活随笔為你收集整理的Python自动化运维之13、异常处理及反射(__import__,getattr,hasattr,setattr)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 强盗分宝石
- 下一篇: UVa11549计算器谜题[floyd判