• (转)Python自动化运维之13、异常处理及反射(__import__,getattr,hasattr,setattr)


    原文:http://www.cnblogs.com/xiaozhiqi/p/5778856.html

    https://blog.csdn.net/zong596568821xp/article/details/78180229------Python异常捕获与处理

     

    一、异常处理

    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()
    那么问题来了?
    a、上述访问对象成员的 name 和 func 是什么? 
    答:是变量名
    b、obj.xxx 是什么意思? 
    答:obj.xxx 表示去obj中或类中寻找变量名 xxx,并获取对应内存地址中的内容。
    c、需求:请使用其他方式获取obj对象中的name变量指向内存中的值 “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、比较三种访问方式

    • 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函数

  • 相关阅读:
    VisualStudio2010配置OpenCV的一种一劳永逸的方法
    QT5 Failed to load platform plugin "windows" 终极解决方式 命令行问题
    轻松学习JavaScript二十二:DOM编程学习之节点操作
    Eclipse中安装TestNG插件
    Java Timer 定时器的使用
    技术开发团队的项目管理工具
    python里一个class可以定义多个构造函数
    python中的多继承
    python基础之使用os.system来执行系统命令
    python下划线变量的含义
  • 原文地址:https://www.cnblogs.com/liujiacai/p/7404451.html
Copyright © 2020-2023  润新知