(轉)Python自動化運維之13、異常處理及反射(__import__,getattr,hasattr,setattr)
Python自動化運維之13、異常處理及反射(__import__,getattr,hasattr,setattr)
一、異常處理
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函數
(轉)Python自動化運維之13、異常處理及反射(__import__,getattr,hasattr,setattr)