zoukankan      html  css  js  c++  java
  • 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时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!!

    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
    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
    更多异常

    实例: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)

    对于上述实例,异常类只能用来处理指定的异常情况,如果非指定异常则无法处理。

    # 未捕获到异常,程序直接报错
     
    s1 = 'hello'
    try:
        int(s1)
    except IndexError as e:
        print(e)
    

    所以,写程序时需要考虑到try代码块中可能出现的任意异常,可以这样写:  

    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,他可以捕获任意异常,即:  

    s1 = 'hello'
    try:
        int(s1)
    except Exception as e:
        print(e)
    

    接下来你可能要问了,既然有这个万能异常,其他异常是不是就可以忽略了!

    答:当然不是,对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行

    s1 = 'hello'
    try:
        int(s1)
    except KeyError as e:
        print('键错误')
    except IndexError as e:
        print('索引错误')
    except Exception as e:
        print('错误')
    

    3、异常其他结构  

    try:
        # 主代码块
        pass
    except KeyError as e:
        # 异常时,执行该块
        pass
    else:
        # 主代码块执行完,执行该块
        pass
    finally:
        # 无论异常与否,最终执行该块
        pass
    

    4、主动触发异常  

    try:
        raise Exception('错误了。。。')
    except Exception as e:
        print(e)
    

    5、自定义异常  

    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、断言  

    # assert 条件
     
    assert 1 == 1
     
    assert 1 == 2
    

    二、反射

      python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr、__import__(module_name)、importlib,改五个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员、导入模块以字符串方式导入。

    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')
    

    详细解析:

    当我们要访问一个对象的成员时,应该是这样操作:

    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()

    结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!

      

    类也是对象

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

    ### 另外一种实现方式

    index2.py

    import importlib
    
    module = "lib.account"
    func_name = "login"
    
    m = importlib.import_module(module)
    func = getattr(m, func_name)
    func()
    

      

      

    利用反射和super()的一个例子:点这里

  • 相关阅读:
    bladex从blade-dev.yaml 读取配置信息
    怎么判断map不为空
    根据来源编号对明细进行分组 跟库存做对比 用到的技术 list根据某个字段分组 Double Long 比较大小
    hibernate根据包名获取该包下实体类,数据库中不存在的库表名称
    hibernate NonUniqueObjectException 一个session中存有两个识别码(id)相同的对象
    正则匹配不包含某些字符 update(?!tdyt)[A-z(]*(qlgz)
    idea常用插件
    Rainbow Roads
    Jumping Haybales (dp)
    01背包
  • 原文地址:https://www.cnblogs.com/xiaozhiqi/p/5778856.html
Copyright © 2011-2022 走看看