Python实例浅谈之二自定义异常

来源:互联网 发布:王者荣耀用java还是c 编辑:程序博客网 时间:2024/05/23 01:31

一、问题

      Python中标准异常集包含的内容已经相当广泛,但有时开发中还须创建自己的异常,比如在特定的标准异常和模块异常中添加额外的信息。
       本例中两个异常都与IOError有关,IOError是一个用于输入/输出的通用异常,可能在无效的文件访问或其他形式的通信中触发。

二、解决

1、创建自定义异常代码

[html] view plain copy
  1. #!/usr/bin/env python  
  2. '''  
  3. $Id$  
  4.   
  5. myexc.py -- "my exceptions" demo which highlights user-created  
  6.     exceptions.  NOTE:  this example does not currently work with  
  7.     JPython as neither the errno nor tempfile modules have been  
  8.     implemented, and also, the socket module is incomplete.  
  9. '''  
  10.   
  11. # import all our needed modules  
  12. import os, socket, errno, types, tempfile  
  13.   
  14. # create our a new NetworkError exception, derived from IOError  
  15. class NetworkError(IOError):  
  16.     pass  
  17.   
  18. # create our a new FileError exception, derived from IOError  
  19. class FileError(IOError):  
  20.     pass  
  21.   
  22. # updArgs --> tuple  
  23. def updArgs(args, newarg=None):  
  24.     '''updArgs(args, newarg=None) -- if instance, grab each exception  
  25.         instance argument and place them in a list; otherwise, just  
  26.         convert given args sequence to a list for mutability; add  
  27.         newarg if necessary; then convert the whole thing to a tuple.'''  
  28.   
  29.     if isinstance(args, IOError):  
  30.         myargs = []  
  31.     myargs.extend([arg for arg in args])  
  32.     else:  
  33.         myargs = list(args)  
  34.   
  35.     if newarg:  
  36.         myargs.append(newarg)  
  37.   
  38.     return tuple(myargs)  
  39.   
  40.   
  41. # fileArgs --> tuple  
  42. def fileArgs(fn, mode, args):  
  43.     '''fileArgs(fn, mode, args) -- similar to updArgs() except made  
  44.         specifically for files; creates small permission string and  
  45.         formats error to be similar to other IOError exceptions.'''  
  46.   
  47.     if args[0] == errno.EACCES and \  
  48.             'access' in dir(os):  
  49.         perms = ''  
  50.         permd = { 'r': os.R_OK, 'w': os.W_OK, \  
  51.                     'x': os.X_OK }  
  52.         pkeys = permd.keys()  
  53.         pkeys.sort()  
  54.         pkeys.reverse()  
  55.   
  56.         for eachPerm in 'rwx':  
  57.             if os.access(fn, permd[eachPerm]):  
  58.                 perms = perms + eachPerm  
  59.             else:  
  60.                 perms = perms + '-'  
  61.   
  62.         if isinstance(args, IOError):  
  63.             myargs = []  
  64.         myargs.extend([arg for arg in args])  
  65.         else:  
  66.             myargs = list(args)  
  67.   
  68.         myargs[1] = "'%s' %s (perms: '%s')" % \  
  69.                     (mode, myargs[1], perms)  
  70.   
  71.         myargs.append(args.filename)  
  72.   
  73.     else:  
  74.         myargs = args  
  75.   
  76.     return tuple(myargs)  
  77.   
  78. # myconnect() --> None (raises exception on error)  
  79. def myconnect(sock, host, port):  
  80.     '''myconnect(sock, host, port) -- attempt to make a network connection  
  81.     with the given socket and host-port pair; raises our new NetworkError  
  82.     exception and collates error number and reason.'''  
  83.   
  84.     try:  
  85.         sock.connect((host, port))  
  86.   
  87.     except socket.error, args:  
  88.         myargs = updArgs(args)        # convert inst to tuple  
  89.         if len(myargs) == 1:        # no #s on some errors  
  90.             myargs = (errno.ENXIO, myargs[0])  
  91.   
  92.         raise NetworkError, \  
  93.             updArgs(myargs, host + ':' + str(port))  
  94.   
  95.   
  96. # myopen() --> file object  
  97. def myopen(fn, mode='r'):  
  98.     '''myopen(fn, mode) -- wrapper around the open() built-in function  
  99.     such that we raise our new FileError exception on an error situation  
  100.     and collate a set of FileError exception arguments to pass to the user'''  
  101.   
  102.     try:  
  103.         fo = open(fn, mode)  
  104.   
  105.     except IOError, args:  
  106.         raise FileError, fileArgs(fn, mode, args)  
  107.   
  108.     return fo  
  109.   
  110.   
  111. # testfile() --> None  
  112. def testfile():  
  113.     '''testfile() -- runs the file tester, setting a variety of test files  
  114.     which should generate FileError exceptions'''  
  115.   
  116.     fn = tempfile.mktemp()      #make temp file and path  
  117.     f = open(fn, 'w')  
  118.     f.close()  
  119.   
  120.     for eachTest in ((0, 'r'), (0100, 'r'), (0400, 'w'), (0500, 'w')):  
  121.         try:  
  122.             os.chmod(fn, eachTest[0])  
  123.             f = myopen(fn, eachTest[1])  
  124.         except FileError, args:  
  125.             print "%s: %s" % \  
  126.                     (args.__class__.__name__, args)  
  127.         else:  
  128.             print fn, "opened ok... perms ignored"  
  129.             f.close()  
  130.   
  131.     os.chmod(fn, 0777)  
  132.     os.unlink(fn)  
  133.   
  134.   
  135. # testnet() --> None  
  136. def testnet():  
  137.     '''testfile() -- runs the network tester, making various connections  
  138.     which should generate NetworkError exceptions'''  
  139.     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
  140.   
  141.     for eachHost in ('127.0.0.1', 'www'):  
  142.         try:  
  143.             myconnect(s, eachHost, 80)  
  144.         except NetworkError, args:  
  145.             print "%s: %s" % (args.__class__.__name__, args)  
  146.         else:  
  147.             print "network connection successful to", `eachHost`  
  148.             s.close()  
  149.   
  150.   
  151. # run tests if invoked as a script  
  152. if __name__ == '__main__':  
  153.     testfile()  
  154.     testnet()  
         程序自定义了两个新的异常类FileError与NetworkError,基类都是IOError,也重新实现了两个诊断版的函数open()[myopen()]和socket.connect([myconnect()],同时包含了一个在直接运行文件时执行的测试函数[test()]。

2、运行结果图

(centos6.5下运行结果:)


        myconnect()仅仅是简单的对套接字的函数conect()进行包装,当网络连接失败时提供一个IOError类型的异常,和一般的socket.error不一样,还提供给程序员主机名和端口号。当失败发生时,错误号和错误字符很有帮助,但是如果结合更精确的主机-端口会更有帮助,因为这一对可能是由某个数据库或名称服务动态生成或重新获得。这些值由connect()加入。另一种情形是无法找到主机,socket.error异常没有直接提供的错误号;为了遵循IOError协议,提供了一个错误号-错误字符串对;查找最接近的错误号,选用的是ENXIO。
        myopen()封装了已经存在的一些代码,这里用的是open()函数,仅仅捕捉IOError异常。所有的其他都忽略并传给下一层(因为没有与它们相关的处理器)。一旦捕捉到IOError就引发自定义的异常并通过 fileArgs()返回值来定制参数。

          上述分别是linux下使用不同的用户运行的结果,root用户拥有操作文件的所有权限。

三、总结

(1)可以总结一个通用的异常模块,包括常见的异常信息提示,这样在项目开发中可以直接导入,重复利用。
(2)raise传递异常,对定位错误信息有很大的帮助,并且可以加入自己喜欢的样式便于调试。

(3)若有更好的设计或思路,请留言,在此先感谢!


From: http://blog.csdn.net/taiyang1987912/article/details/44155139

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子在学校老师打孩子家长怎么办? 宝宝不听话我老忍不住打他怎么办 两岁宝宝断母乳不愿意喝奶粉怎么办 2岁半的宝宝叛逆不听话怎么办? 2岁半宝宝说什么不听话怎么办? 误把脱毛膏当牙膏用了刷牙怎么办 儿子1岁5个月了不说话怎么办 两岁小儿不会说话和智商低怎么办 宝宝不会说话教他说他不愿意怎么办 25个月宝宝不愿意学说话怎么办 老师说小孩在幼儿园老是说话怎么办 在外留学想领养一个外国小孩怎么办 三岁半的宝宝想去美国上学怎么办 农村新房边的老老祖坟不搬怎么办 倒西太阳晒的房子夏天很热怎么办 客厅壁纸用的浅灰色影视墙怎么办 我喜欢玩手机游戏妈妈很生气怎么办 家里墙上有很多白色的虫子怎么办 3岁半宝宝学数字学不会怎么办 小孩子读一年级拼音读不好要怎么办 4个月的婴儿恶心干呕怎么办 生了小孩后胆汁酸偏高怎么办 9个月宝宝吃盐了怎么办 两个月宝宝母乳拉大便太稀怎么办呀 两个月的宝宝不拉大便怎么办 两个月宝宝五天没拉大便怎么办 4个月宝宝不拉大便怎么办 2个月宝宝3天没拉大便怎么办 宝宝拉不出大便老是憋的哭怎么办 九个月的宝宝不爱吃水果怎么办 顺产侧切伤口发炎化脓有臭味怎么办 一岁宝宝感冒发烧39度怎么办 宝宝二岁半了只吃水果不吃饭怎么办 8个月小孩发烧39度怎么办 咳嗽吃了很多药都不见效果怎么办 生完孩子半个月奶水越来越少怎么办 买到了坏了的水果商家不赔怎么办 小孩奶不够吃又不吃奶粉怎么办 10个月的宝宝便秘很严重怎么办 四岁的宝宝突然不怎么吃饭怎么办 1岁7个月宝宝突然不爱吃饭怎么办