python中用来回溯异常的模块_python中的异常处理使用说明
Python的異常處理能力是很強(qiáng)大的,可向用戶準(zhǔn)確反饋出錯信息。在Python中,異常也是對象,可對它進(jìn)行操作。所有異常都是基類Exception的成員,所有異常都從基類Exception繼承,而且都在exceptions模塊中定義,Python自動將所有異常名稱放在內(nèi)建命名空間中,所以程序不必導(dǎo)入exceptions模塊即可使用異常。
一旦引發(fā)而且沒有捕捉SystemExit異常,程序執(zhí)行就會終止。如果交互式會話遇到一個(gè)未被捕捉的SystemExit異常,會話就會終止。
一、異常的捕獲??? 異常的捕獲有以下幾種方法:
1:使用try和except語句
代碼如下
try:
block
except [exception,[data…]]:
block
try:
block
except [exception,[data...]]:
block
else:
block
該種異常處理語法的規(guī)則是:
? 執(zhí)行try下的語句,如果引發(fā)異常,則執(zhí)行過程會跳到第一個(gè)except語句。
? 如果第一個(gè)except中定義的異常與引發(fā)的異常匹配,則執(zhí)行該except中的語句。
? 如果引發(fā)的異常不匹配第一個(gè)except,則會搜索第二個(gè)except,允許編寫的except數(shù)量沒有限制。
? 如果所有的except都不匹配,則異常會傳遞到下一個(gè)調(diào)用本代碼的最高層try代碼中。
? 如果沒有發(fā)生異常,則執(zhí)行else塊代碼。
示例代碼:
代碼如下
try:
f = open(“file.txt”,”r”)
except IOError, e:
print e
捕獲到的IOError錯誤的詳細(xì)原因會被放置在對象e中,然后運(yùn)行該異常的except代碼塊,也可以使用以下方法來捕獲所有的異常:
代碼如下
try:
a=b
b=c
except Exception,ex:
print Exception,":",ex
使用except子句需要注意的事情,就是多個(gè)except子句截獲異常時(shí),如果各個(gè)異常類之間具有繼承關(guān)系,則子類應(yīng)該寫在前面,否則父類將會直接截獲子類異常,放在后面的子類異常也就不會執(zhí)行到了。
2:使用try跟finally
代碼如下
try:
block
finally:
block
該語句的執(zhí)行規(guī)則是:
? 執(zhí)行try下的代碼。
? 如果發(fā)生異常,在該異常傳遞到下一級try時(shí),執(zhí)行finally中的代碼。
? 如果沒有發(fā)生異常,則執(zhí)行finally中的代碼。
第二種try語法在無論有沒有發(fā)生異常都要執(zhí)行代碼的情況下是很有用的,例如我們在python中打開一個(gè)文件進(jìn)行讀寫操作,我在操作過程中不管是否出現(xiàn)異常,最終都是要把該文件關(guān)閉的。
這兩種形式相互沖突,使用了一種就不允許使用另一種,而功能又各異。
二、手工引發(fā)引發(fā)一個(gè)異常
在Python中,要想引發(fā)異常,最簡單的形式就是輸入關(guān)鍵字raise,后跟要引發(fā)的異常的名稱。異常名稱標(biāo)識出具體的類:Python異常是那些類的對象,執(zhí)行raise語句時(shí),Python會創(chuàng)建指定的異常類的一個(gè)對象,raise語句還可指定對異常對象進(jìn)行初始化的參數(shù),為此,請?jiān)诋惓n惖拿Q后添加一個(gè)逗號以及指定的參數(shù)(或者由參數(shù)構(gòu)成的一個(gè)元組)。
示例代碼:
代碼如下
try:
raise MyError #自己拋出一個(gè)異常
except MyError:
print 'a error'
raise ValueError,'invalid argument'
捕捉到的內(nèi)容為:
代碼如下
type = VauleError
message = invalid argument
三、跟蹤查看異常
發(fā)生異常時(shí),Python能“記住”引發(fā)的異常以及程序的當(dāng)前狀態(tài),Python還維護(hù)著traceback(跟蹤)對象,其中含有異常發(fā)生時(shí)與函數(shù)調(diào)用堆棧有關(guān)的信息,異常可能在一系列嵌套較深的函數(shù)調(diào)用中引發(fā),程序調(diào)用每個(gè)函數(shù)時(shí),Python會在“函數(shù)調(diào)用堆棧”的起始處插入函數(shù)名,一旦異常被引發(fā),Python會搜索一個(gè)相應(yīng)的異常處理程序。
如果當(dāng)前函數(shù)中沒有異常處理程序,當(dāng)前函數(shù)會終止執(zhí)行,Python會搜索當(dāng)前函數(shù)的調(diào)用函數(shù),并以此類推,直到發(fā)現(xiàn)匹配的異常處理程序,或者Python抵達(dá)主程序?yàn)橹?#xff0c;這一查找合適的異常處理程序的過程就稱為“堆棧輾轉(zhuǎn)開解”(Stack Unwinding)。解釋器一方面維護(hù)著與放置堆棧中的函數(shù)有關(guān)的信息,另一方面也維護(hù)著與已從堆棧中“輾轉(zhuǎn)開解”的函數(shù)有關(guān)的信息。
代碼如下
try:
block
except:
traceback.print_exc()
四、采用sys模塊回溯最后的異常
代碼如下
import sys
try:
block
except:
info=sys.exc_info()
print info[0],":",info[1]
或者以如下的形式:
代碼如下
import sys
tp,val,td = sys.exc_info()
sys.exc_info()的返回值是一個(gè)tuple, (type, value/message, traceback)
這里的type是異常的類型,value/message是異常的信息或者參數(shù),traceback包含調(diào)用棧信息的對象,從這點(diǎn)上可以看出此方法涵蓋了traceback。
以上都是錯誤處理的理論知識,接下來我們要動手設(shè)計(jì)一個(gè)自己的異常處理類,用來記錄異常日志,將錯誤的日志按照每小時(shí)一個(gè)文件的頻率,保存到我們指定的位置。代碼如下:
代碼如下
#coding:utf-8
#基于python2.6
import logging,os,time,traceback
class LOG:
def __init__(self,logger):
self.fileHandlerName = ''
self.fileHandler = None
self.loggerName = logger
self.logger = logging.getLogger(logger)
self.logger.setLevel(logging.DEBUG)
self.formatter = logging.Formatter("=========================ntime:%(asctime)s nlogger:%(name)s nlevel:%(levelname)s nfile:%(filename)s nfun:%(funcName)s nlineno:%(lineno)d nmessage:%(message)s")
# 控制臺
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(self.formatter)
self.logger.addHandler(ch)
path = os.path.abspath(os.path.dirname(__file__)) + '/log/'+self.loggerName+'/'
print 'log path=',path
def setfh(self):
fname = time.strftime("%Y%m%d%H")
if fname!=self.fileHandlerName:
#移除原來的句柄
if self.fileHandler!=None :
self.logger.removeHandler(self.fileHandler)
#設(shè)置日志文件保存位置
path = os.path.abspath(os.path.dirname(__file__)) + '/log/'+self.loggerName+'/'
print path
if os.path.isdir(path) == False:
os.makedirs(path)
fh = logging.FileHandler(path+fname+'.log')
fh.setLevel(logging.DEBUG)
fh.setFormatter(self.formatter)
self.logger.addHandler(fh)
self.fileHandlerName = fname
self.fileHandler = fh
#格式化日志內(nèi)容
def _fmtInfo(self,msg):
if len(msg)==0:
msg = traceback.format_exc()
return msg
else:
_tmp = [msg[0]]
_tmp.append(traceback.format_exc())
return 'n**********n'.join(_tmp)
#封裝方法
def debug(self,*msg):
_info = self._fmtInfo(msg)
try:
self.setfh()
self.logger.debug(_info)
except:
print 'mylog debug:' + _info
def error(self,*msg):
_info = self._fmtInfo(msg)
try:
self.setfh()
self.logger.error(_info)
except:
print 'mylog error:' + _info
def info(self,*msg):
_info = self._fmtInfo(msg)
try:
self.setfh()
self.logger.error(_info)
except:
print 'mylog info:' + _info
def warning(self,*msg):
_info = self._fmtInfo(msg)
try:
self.setfh()
self.logger.error(_info)
except:
print 'mylog warning:' + _info
if __name__=='__main__':
log = LOG('fight')
try:
print 1/0
except:
log.error() #使用系統(tǒng)自己的錯誤描述
try:
print 2/0
except:
log.error('搞錯了,分母不能為0')
#使用自己的錯誤描述
運(yùn)行一下,我們會在該文件目錄下的log/fight下看到一個(gè)日志文件
總結(jié)
以上是生活随笔為你收集整理的python中用来回溯异常的模块_python中的异常处理使用说明的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 汽车仪表盘89:18是什么意思?
- 下一篇: 四川省江安县江安镇竹海路126附11号属