Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 466|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-1 03:52:00 | 显示全部楼层 |阅读模式

    一、异常处理

    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()的一个例子:点这里

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-23 08:52 , Processed in 0.063087 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表