第十九天- 约束 异常处理 日志使用
# 类的约束:
1 # 为何要用,在哪里遇到? 2 3 # 例:贴吧登录(若不同人来写) 4 class Normal: # 张三版 5 def login(self): 6 print("普通账号登录") 7 8 class Member: # 李四版 9 def login(self): 10 print("吧务账号登录") 11 12 class Admin: # 王二版 13 def denglu(self): 14 print("管理员登陆") 15 16 项目经理 17 def login(obj): 18 obj.login() 19 # 20 n = Normal() 21 login(n) 22 23 m = Member() 24 login(m) 25 26 a = Admin() 27 login(a) # 报错 'Admin' object has no attribute 'login' 28 29 # 所以有统一调用时,要避免这样的调用不了,要约束程序的结构.也就是说. 30 # 分配任务之前就应该把功能定义好.然后分别给底下的程序员来完成相应功能
# 方法一 抛异常 (常用)
'''
提取⽗类.然后在⽗类中定义好⽅法.在这个⽅法中什么都不⽤⼲.就抛⼀个异
常就可以了.这样所有的⼦类都必须重写这个⽅法.否则.访问的时候就会报错.
(尽量抛出的是NotImplementError. 这样比较专业, ⽽且错误比较明确)
'''
1 class Base: # 项目经理 先定好规范 2 def login(self): # 强制子类做xxx事情(方法) 3 raise NotImplementedError("子类没有实现该方法") # 不做就报错 抛异常 4 5 class Normal(Base): # 张三版 6 def login(self): 7 print("普通账号登录") 8 9 class Member(Base): # 李四版 10 def login(self): # 对login方法的覆盖重写 11 print("吧务账号登录") 12 13 class Admin(Base): # 王二版 14 # def denglu(self): # 这里方法不是login就没有覆盖 15 def login(self): 16 print("管理员登陆") 17 18 19 def login(obj): # 项目经理调用 20 obj.login() 21 22 n = Normal() 23 login(n) # 当Normal (子类) 去执行login时,先回找自身,自己有所以直接执行,也就不会报错了 24 25 m = Member() 26 login(m) 27 28 # a = Admin() 29 # login(a) # 当Admin (子类) 去执行login时,会先回找自身,但他这里自己没有,所以会去父类找login,也就是执行力父类的报错 30 # 报错 NotImplementedError: 子类没有实现该方法 31 32 a = Admin() 33 login(a)
# 方案二 写抽象类和抽象⽅法 来约束子类
'''
我们如果写⼀个⽅法.不知道⽅法的内部应该到底写什么. 那这个⽅法其实就应该是⼀个抽象的⽅法.
如果⼀个类中包含抽象⽅法. 那么这个类⼀定是⼀个抽象类.抽象类是不能有实例的.如.你看看⼀些
抽象派画作.现实中是不存在的.也就⽆法建立实例对象与之相对应.所以抽象类⽆法创建对象.创时会报错
'''
1 from abc import ABCMeta,abstractmethod # 原类 抽象 2 # 贴吧登录 3 class Base(metaclass=ABCMeta): # 项目经理 抽象类 4 @abstractmethod # 抽象方法 5 def login(self): # 约束子类 6 pass 7 8 def hehe(self): # 抽象类中可以有正常方法 9 print("呵呵呵") 10 11 # b = Base() # 报错的. 原因是Base是一个抽象类. 含有抽象方法. 不允许创建对象的 12 13 14 class Normal(Base): # 张三版 15 def login(self): # 子类对抽象的内容给出具体的实现 . 重写 16 print("普通账号登录") 17 18 class Member(Base): # 李四版 19 def login(self): # 子类对抽象的内容给出具体的实现 . 重写 20 print("吧务账号登录") 21 22 class Admin(Base): # 王二版 23 # def denglu(self): # 报错 继承了前面的抽象必须覆盖 24 def login(self): 25 print("管理员登陆") 26 27 28 def login(obj): # 项目经理调用 29 obj.login() 30 31 32 n = Normal() 33 login(n) 34 35 m = Member() 36 login(m) 37 38 a = Admin() 39 login(a)
# 抽象类. 含有抽象方法. 不允许创建对象
# 一个类如果全部都是抽象方法. 这个类可以被称为接口. 用来约束子类和规范子类
# 总结
''' 当我们需要对子类进行约束: 1.抛出异常 NotImplementedError() 没有实现 -> 约定俗成. 多观察 2.写抽象类 from abc import ABCMeta, abstractmethod class Base(metaclass = ABCMeta): @abstractmethod def 方法(self): pass 如果一个类中包含了抽象方法. 那么这个类一定是一个抽象类 一个抽象类中可以包含正常的方法 接口: 接口中所有的方法都是抽象方法 子类必须重写父类中的抽象方法. 否则子类也是一个抽象类 '''
# 异常处理 try...except
# 写法(语法)
try:
'''操作'''
except '错误名称' as 别名:
'''出现错误的时候. 要干什么...'''
except '错误名称' as 别名:
'''出现错误的是偶. 要干什么'''
except Exception as e:
'''异常的父类,可以捕获所有的异常'''
else:
'''保护部抛出异常的代码,当try中无异常时执行'''
finally:
'''最后执行这里'''
'''
解读:程序先执⾏操作,然后如果出错了会走except中的代码.如果不出错,执⾏else中
的代码.不论处不出错.最后都要执⾏finally中的语句.⼀般我们⽤try...except就够⽤了.
顶多加上finally. finally⼀般⽤来作为收尾⼯作.
'''
try: print(1/0) # 0不能做除数 ZeroDivisionError: division by zero except ZeroDivisionError as z: print("错了. 除数不能为0") import traceback # 计算a+b def cul(a, b): if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float): return a + b else: # 在这里有两种方案. 1. 直接返回 , 2. 抛出异常 # raise 抛出 Exception 错误和异常,所有错误的根 raise Exception("我要的不是这个. 你应该我传递int或者float") try: print(cul(1,2)) print(cul(1,"疙瘩汤")) except Exception as e: # 获取错误信息 访问堆栈信息 print(traceback.format_exc()) # 获取堆栈信息 一般不这么写 装日志 print("有误") # 打印是给客户看的
# 日志(固定套路,用时照搬):
# 1. 导入logging模块.
# 2. 简单配置⼀下logging
# 3. 出现异常的时候(except). 向⽇志⾥写错误信息.
1 import logging 2 # filename: ⽂件名 3 # format: 数据的格式化输出. 最终在⽇志⽂件中的样⼦ 4 # 时间-名称-级别-模块: 错误信息 5 # datefmt: 时间的格式 6 # level: 错误的级别权重, 当错误的级别权重⼤于等于leval的时候才会写⼊⽂件 7 logging.basicConfig(filename='x1.log', 8 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', 9 datefmt='%Y-%m-%d %H:%M:%S', 10 level=30) 11 # 当前配置表示 0以上的分数会被写⼊⽂件 12 # CRITICAL = 50 13 # FATAL = CRITICAL 14 # ERROR = 40 15 # WARNING = 30 16 # WARN = WARNING 17 # INFO = 20 18 # DEBUG = 10 19 # NOTSET = 0 20 logging.critical("我是critical") # 50分. 最贵的 21 logging.error("我是error") # 40分 22 logging.warning("我是warning") # 30分 23 logging.info("我是info") 24 logging.debug("我是debug") 25 logging.log(1, "我什么都不是")
1 # 例子,接上面 2 import traceback 3 try: 4 print(1/0) 5 except Exception: 6 logging.error(traceback.format_exc()) # 用法 7 print("出错了")
# 把⽇志⽂件分开 FileHandler
1 import logging 2 # 创建⼀个操作⽇志的对象logger(依赖FileHandler) 3 file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8') 4 file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")) 5 logger1 = logging.Logger('A系统', level=logging.ERROR) 6 logger1.addHandler(file_handler) 7 logger1.error('我是A系统') 8 9 10 # 再创建⼀个操作⽇志的对象logger(依赖FileHandler) 11 file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8') 12 file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s")) 13 logger2 = logging.Logger('B系统', level=logging.ERROR) 14 logger2.addHandler(file_handler2) 15 logger2.error('我是B系统')