• python学习13-类的约束 异常处理 日志


    一 、约束

    python中约束有两种

    第一种,通过抛异常进行约束,这种是子类不按我要求的来,我就给你抛异常(推荐)

    操作:提取一个父类. 在父类中给出一个方法。但在方法中不给出任何代码,直接抛异常

    # 贴吧
    # 项目经理(级别高一点儿)
    class Base:
    def login(self): # 强制子类做xxxx事
    raise NotImplementedError("子类没有实现该方法") # 报错. 抛异常

    # 1. 普通账号 --> 翔哥
    class Normal(Base):
    def login(self):
    print("普通账号的登录")

    # 2. 吧务 - > 强哥
    class Member(Base):
    def login(self):
    print("吧务的登录")

    # 3. 百度员工 -> 明哥
    class Admin(Base):
    def denglu(self):
    print("管理员的登录")

    # 项目经理
    def wodetian(obj):
    obj.login()

    n = Normal()
    wodetian(n)

    m = Member()
    wodetian(m)

    a = Admin()
    wodetian(a) #这就会抛出异常,因为没按要求写,找不到login

    异常约束

    复制代码
     1  # 贴吧
     2  # 项目经理(级别高一点儿)
     3  class Base:
     4      def login(self): # 强制子类做xxxx事
     5          raise NotImplementedError("子类没有实现该方法") # 报错. 抛异常
     6 
     7  # 1. 普通账号  -->  翔哥
     8  class Normal(Base):
     9      def login(self):
    10          print("普通账号的登录")
    11 
    12  # 2. 吧务  - > 强哥
    13  class Member(Base):
    14      def login(self):
    15          print("吧务的登录")
    16 
    17  # 3. 百度员工  -> 明哥
    18  class Admin(Base):
    19      def denglu(self): 
    20          print("管理员的登录")
    21 
    22  # 项目经理
    23  def wodetian(obj):
    24      obj.login()
    25 
    26  n = Normal()
    27  wodetian(n)
    28 
    29  m = Member()
    30  wodetian(m)
    31 
    32  a = Admin()
    33  wodetian(a)   #这就会抛出异常,因为没按要求写,找不到login
    复制代码

    第二种,通过抽象类和抽象方法进行约束,这种是子类不按我要求的来,我就不让子类实例化

    操作:提取一个父类,将父类中给出的方法定义为抽象方法,不必实现,直接pass

    ### 这些概念要记住:

    抽象类是不能进行实例化的

    如果一个类中有抽象方法,那么这个类就是抽象类

    一个抽象类可以有非抽象方法

    from abc import ABCMeta, abstractmethod

    class Base(metaclass=ABCMeta): # 抽象类
    # 抽象方法
    @abstractmethod
    def login(self): # 强制子类做xxxx事,子类必须重写这个方法
    pass

    class Normal(Base):
    def login(self):
    print("普通登录")

    class Member(Base):
    def login(self):
    print("会员登录")

    class Admin(Base):
    def denglu(self):
    print('管理员登录')

    def denglu(obj):
    obj.login()
    n = Normal()
    denglu(n)
    m = Member()
    denglu(m)
    a = Admin() #Can't instantiate abstract class admin with abstract methods login
    denglu(a)

    抽象约束

    复制代码
     1 from abc import ABCMeta, abstractmethod
     2 
     3 class Base(metaclass=ABCMeta): # 抽象类
     4      # 抽象方法
     5      @abstractmethod
     6      def login(self):          # 强制子类做xxxx事,子类必须重写这个方法
     7          pass
     8 
     9 class Normal(Base):
    10     def login(self):
    11         print("普通登录")
    12 
    13 class Member(Base):
    14     def login(self):
    15         print("会员登录")
    16 
    17 class Admin(Base):
    18     def denglu(self):
    19         print('管理员登录')
    20 
    21 def denglu(obj):
    22     obj.login()
    23 n = Normal()
    24 denglu(n)
    25 m = Member()
    26 denglu(m)
    27 a = Admin()  #Can't instantiate abstract class admin with abstract methods login
    28 denglu(a)
    复制代码

    二、异常处理

    格式:

    try:

      代码块

    except  错误名 as 别名:

      出现该错误时做什么

    except 错误名 as  别名:

      出现该错误时做什么

    ...

    else:

      不出错时执行这里

    finally:

      出不出错都执行这里

    解读: 程序先执行操作, 然后如果出错了会走except中的代码. 如果不出错, 执行else中的代码. 不论出不出错. 最后都要执行finally中的语句. 一般我们用try...except就够了. 顶多加上finally. finally一般用来作为收尾工作。

    def cul(a,b):
    if (type(a)== int or type(a) == float) and (type(b)== int or type(b)== float):
    return a+b
    else:
    raise Exception("我要的是数字,你输入的是啥")

    try:
    print(cul("一",4))
    except Exception as e:
    print("错了,你要输入数字")

    异常处理

    复制代码
     1 def cul(a,b):
     2     if (type(a)== int or type(a) == float) and (type(b)== int or type(b)== float):
     3         return a+b
     4     else:
     5         raise Exception("我要的是数字,你输入的是啥")
     6 
     7 try:
     8     print(cul("一",4))
     9 except Exception as e:
    10     print("错了,你要输入数字")
    复制代码

    ##抛异常

    抛异常要用到关键字raise

    def add(a, b):
    '''
    给我传递两个整数. 我帮你计算两个数的和
    :param :param a:
    :param :param b:
    :return :return:
    '''
    if not type(a) == int and not type(b) == int:
    # 当程序运行到这句话的时候. 整个函数的调用会被中断. 并向外抛出一个异常.
    raise Exception("不是整数, 朕不能帮你搞定这么复杂的运算.")
    return a + b
    # 如果调用方不处理异常. 那产生的错误将会继续向外抛. 最后就抛给了用户
    add("你好", "我叫赛利亚")
    # 如果调用方处理了异常. 那么错误就不会丢给用户. 程序也能正常进行
    try:
    add("胡辣汤", "滋滋冒油的大腰子")
    except Exception as e:
    print("报错了. 我要的是数字")

    raise

    复制代码
     1 def add(a, b):
     2  '''
     3  给我传递两个整数. 我帮你计算两个数的和
     4  :param :param a:
     5  :param :param b:
     6  :return :return:
     7  '''
     8  if not type(a) == int and not type(b) == int:
     9  # 当程序运行到这句话的时候. 整个函数的调用会被中断. 并向外抛出一个异常.
    10  raise Exception("不是整数, 朕不能帮你搞定这么复杂的运算.")
    11  return a + b
    12 # 如果调用方不处理异常. 那产生的错误将会继续向外抛. 最后就抛给了用户
    13 add("你好", "我叫赛利亚")
    14 # 如果调用方处理了异常. 那么错误就不会丢给用户. 程序也能正常进行
    15 try:
    16  add("胡辣汤", "滋滋冒油的大腰子")
    17 except Exception as e:
    18  print("报错了. 我要的是数字")
    复制代码

    ##自定义异常

     非常简单. 只要你的类继承了Exception类. 那你的类就是一个异常类

    格式:

    def  异常名(Exception):

      pass

    #自定义异常
    class GenderException(Exception):
    pass

    class Person:

    def __init__(self,name,gender):
    self.name = name
    self.gender = gender

    def goto_nan(self):
    if self.gender !="男":
    raise GenderException("性别不对")
    else:
    print("欢迎光临")
    try:
    p1 = Person('alex', '男')
    p1.goto_nan()

    p2 = Person('妖姬', '女')
    p2.goto_nan()

    except GenderException as e:
    print("你来错地儿了")
    except Exception as e:
    print("其他错误")

    自定义异常

    复制代码
     1 #自定义异常
     2 class GenderException(Exception):
     3     pass
     4 
     5 class Person:
     6 
     7     def __init__(self,name,gender):
     8         self.name = name
     9         self.gender = gender
    10 
    11     def goto_nan(self):
    12         if self.gender !="男":
    13             raise GenderException("性别不对")
    14         else:
    15             print("欢迎光临")
    16 try:
    17     p1 = Person('alex', '男')
    18     p1.goto_nan()
    19 
    20     p2 = Person('妖姬', '女')
    21     p2.goto_nan()
    22 
    23 except GenderException as e:
    24     print("你来错地儿了")
    25 except Exception as e:
    26     print("其他错误")
    复制代码

    ##异常处理好是好,但是有一个问题,我们在调试的时候是希望看到程序哪里出现问题的,而异常处理没有具体的错误信息,那这么办呢?这时需要引入另一个模块traceback. 这个模块可以获取到我们每个方法的调用信息. 又被称为堆栈信息. 这个信息对我们排错是很有帮助的.

    import traceback

    # 继承Exception. 那这个类就是一个异常类 自定义异常
    class GenderError(Exception):
    pass
    class Person:
    def __init__(self, name, gender):
    self.name = name
    self.gender = gender

    def nan_zao_tang_xi_zao(person):
    if person.gender != "男":
    raise GenderError("性别不对. 这里是男澡堂子")

    p1 = Person("alex", "男")
    p2 = Person("eggon", "蛋")
    # nan_zao_tang_xi_zao(p1)
    # nan_zao_tang_xi_zao(p2) # 报错. 会抛出一个异常: GenderError

    # 处理异常
    try:
    nan_zao_tang_xi_zao(p1)
    nan_zao_tang_xi_zao(p2)
    except GenderError as e:
    val = traceback.format_exc() # 获取到堆栈信息
    print(e) # 性别不对. 这里是男澡堂子
    print(val)
    except Exception as e:
    print("反正报错了")
    结果:
    性别不对. 这里是男澡堂子
    Traceback (most recent call last):
    File "/Users/sylar/PycharmProjects/oldboy/面向对象/day05.py", line 155, in
    <module>
    nan_zao_tang_xi_zao(p2)
    File "/Users/sylar/PycharmProjects/oldboy/面向对象/day05.py", line 144, in
    nan_zao_tang_xi_zao
    raise GenderError("性别不对. 这里是男澡堂子")
    GenderError: 性别不对. 这里是男澡堂子

    复制代码
     1 import traceback
     2 
     3 # 继承Exception. 那这个类就是一个异常类  自定义异常
     4 class GenderError(Exception):
     5      pass
     6 class Person:
     7      def __init__(self, name, gender):
     8          self.name = name
     9          self.gender = gender
    10 
    11 def nan_zao_tang_xi_zao(person):
    12      if person.gender != "男":
    13          raise GenderError("性别不对. 这里是男澡堂子")
    14 
    15 p1 = Person("alex", "男")
    16 p2 = Person("eggon", "蛋")
    17 # nan_zao_tang_xi_zao(p1)
    18 # nan_zao_tang_xi_zao(p2) # 报错. 会抛出一个异常: GenderError
    19 
    20 # 处理异常
    21 try:
    22      nan_zao_tang_xi_zao(p1)
    23      nan_zao_tang_xi_zao(p2)
    24 except GenderError as e:
    25      val = traceback.format_exc() # 获取到堆栈信息
    26      print(e) # 性别不对. 这里是男澡堂子
    27      print(val)
    28 except Exception as e:
    29      print("反正报错了")        
    30 结果:
    31 性别不对. 这里是男澡堂子
    32 Traceback (most recent call last):
    33  File "/Users/sylar/PycharmProjects/oldboy/面向对象/day05.py", line 155, in
    34 <module>
    35      nan_zao_tang_xi_zao(p2)
    36  File "/Users/sylar/PycharmProjects/oldboy/面向对象/day05.py", line 144, in
    37 nan_zao_tang_xi_zao
    38      raise GenderError("性别不对. 这里是男澡堂子")
    39 GenderError: 性别不对. 这里是男澡堂子
    复制代码

    这样我们就能收放放如了. 当测试代码的时候把堆栈信息打印出来. 但是当到了 线上的生产环境的时候把这个堆栈去掉即可

    三、日志(不用记,知道怎么用就行)

    当出现任何错误的时候. 我们都可以去日志系统里去查. 看哪里出了问题. 这样在解决问题和bug的时候就多了一个帮手。

    那如何在python中创建这个日志系统呢? 

    1. 导入logging模块.

    2. 简单配置一下logging

    3. 出现异常的时候(except). 向日志里写错误信息.

    复制代码
     1 #参数解释
     2 # filename: 文件名
     3 # format: 数据的格式化输出. 最终在日志文件中的样子
     4 # 时间-名称-级别-模块: 错误信息
     5 # datefmt: 时间的格式
     6 # level: 错误的级别权重, 当错误的级别权重大于等于leval的时候才会写入文件
     7 
     8 import logging  #导入模块
     9 #简单配置,一般只需修改level值
    10 logging.basicConfig(filename='x1.txt',
    11  format='%(asctime)s - %(name)s - %(levelname)s -%
    12 (module)s: %(message)s',
    13  datefmt='%Y-%m-%d %H:%M:%S',
    14 level=0) # 当前配置表示 0以上的分数会被写入文件
    15 # CRITICAL = 50
    16 # FATAL = CRITICAL
    17 # ERROR = 40
    18 # WARNING = 30
    19 # WARN = WARNING
    20 # INFO = 20
    21 # DEBUG = 10
    22 # NOTSET = 0
    23 logging.critical("我是critical") # 写入critical级别信息
    24 logging.error("我是error") # 写入error级别信息
    25 logging.warning("我是警告") # 警告 
    26 logging.info("我是基本信息") # 
    27 logging.debug("我是调试")  
    28 logging.log(2, "我是自定义") # 自定义.  第一个参数可以自己给值,第二个是往日志文件里写的内容
    复制代码

    1 import logging
    2
    3 logging.basicConfig(filename='x1.log',
    4 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
    5 datefmt='%Y-%m-%d %H:%M:%S',
    6 level=35) # 当前配置表示 35以上的级别会被写入文件
    7
    8 import traceback
    9 try:
    10 print(1/0)
    11 except Exception:
    12 logging.error(traceback.format_exc()) # 写入error信息
    13 logging.log(36, traceback.format_exc()) # 自定义写入
    14 print("出错了")
    15 结果:
    16 x1.txt内容
    17
    18 2018-11-12 20:43:01 - root - ERROR -日志系统: Traceback (most recent call last):
    19 File "D:/PyCharm/workspace/day019 约束/日志系统.py", line 29, in <module>
    20 print(1/0)
    21 ZeroDivisionError: division by zero
    22
    23 2018-11-12 20:43:01 - root - Level 36 -日志系统: Traceback (most recent call last):
    24 File "D:/PyCharm/workspace/day019 约束/日志系统.py", line 29, in <module>
    25 print(1/0)
    26 ZeroDivisionError: division by zero

    日志应用

    复制代码
     1  1 import logging
     2  2 
     3  3 logging.basicConfig(filename='x1.log',
     4  4      format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
     5  5      datefmt='%Y-%m-%d %H:%M:%S',
     6  6     level=35)  # 当前配置表示 35以上的级别会被写入文件
     7  7 
     8  8 import traceback
     9  9 try:
    10 10     print(1/0)
    11 11 except Exception:
    12 12     logging.error(traceback.format_exc()) # 写入error信息
    13 13     logging.log(36, traceback.format_exc())  # 自定义写入
    14 14     print("出错了")
    15 15 结果:
    16 16 x1.txt内容
    17 17 
    18 18 2018-11-12 20:43:01 - root - ERROR -日志系统: Traceback (most recent call last):
    19 19   File "D:/PyCharm/workspace/day019 约束/日志系统.py", line 29, in <module>
    20 20     print(1/0)
    21 21 ZeroDivisionError: division by zero
    22 22 
    23 23 2018-11-12 20:43:01 - root - Level 36 -日志系统: Traceback (most recent call last):
    24 24   File "D:/PyCharm/workspace/day019 约束/日志系统.py", line 29, in <module>
    25 25     print(1/0)
    26 26 ZeroDivisionError: division by zero
    复制代码

    ##

    最后, 如果你系统中想要把日志文件分开. 比如. 有个大项目, 有两个子系统, 那两个子系 统要分开记录日志. 方便调试. 那怎么办呢? 注意. 用上面的basicConfig是搞不定的. 我们要借助文件助手(FileHandler), 来帮我们完成日志的分开记录

    import logging

    # 创建一个操作日志的对象logger(依赖FileHandler)
    file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8')
    file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))

    logger1 = logging.Logger('a系统', level=logging.ERROR) #级别
    logger1.addHandler(file_handler) #把文件助手和日志对象绑定
    logger1.error('我是A系统') #写入日志信息

    # 再创建一个操作日志的对象logger(依赖FileHandler)
    file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8')
    file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))

    logger2 = logging.Logger('b系统', level=logging.ERROR) #级别
    logger2.addHandler(file_handler2)
    logger2.error('我是B系统') #写入日志信息

    日志分开

    复制代码
     1 import logging
     2 
     3 # 创建一个操作日志的对象logger(依赖FileHandler)
     4 file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8')
     5 file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))
     6 
     7 logger1 = logging.Logger('a系统', level=logging.ERROR)  #级别
     8 logger1.addHandler(file_handler)   #把文件助手和日志对象绑定
     9 logger1.error('我是A系统')   #写入日志信息
    10 
    11 # 再创建一个操作日志的对象logger(依赖FileHandler)
    12 file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8')
    13 file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))
    14 
    15 logger2 = logging.Logger('b系统', level=logging.ERROR)  #级别
    16 logger2.addHandler(file_handler2)
    17 logger2.error('我是B系统')  #写入日志信息
    复制代码
     
  • 相关阅读:
    ubuntu14.0 服务器webmin安装
    python如何简单的处理图片(1):打开显示
    如何在YouTube上下载视频
    Ubuntu下下载使用sublime
    IndentationError: unexpected indent
    Linux下vim显示行数
    Linux下tree的使用介绍
    Mac利用分屏spliter
    redis开机自启动脚本(linux)
    java 反射应用
  • 原文地址:https://www.cnblogs.com/wuyufeng-9-14/p/10387572.html
Copyright © 2020-2023  润新知