第十九天- 约束 异常处理 日志使用


# 类的约束:
 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)
View Code

 

# 方案二  写抽象类和抽象⽅法 来约束子类
'''
我们如果写⼀个⽅法.不知道⽅法的内部应该到底写什么. 那这个⽅法其实就应该是⼀个抽象的⽅法.
如果⼀个类中包含抽象⽅法. 那么这个类⼀定是⼀个抽象类.抽象类是不能有实例的.如.你看看⼀些
抽象派画作.现实中是不存在的.也就⽆法建立实例对象与之相对应.所以抽象类⽆法创建对象.创时会报错
'''
 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)
View Code
# 抽象类. 含有抽象方法. 不允许创建对象
# 一个类如果全部都是抽象方法. 这个类可以被称为接口. 用来约束子类和规范子类
# 总结
'''
当我们需要对子类进行约束:
    1.抛出异常 NotImplementedError()  没有实现   -> 约定俗成.  多观察
    2.写抽象类
        from abc import ABCMeta, abstractmethod
        class Base(metaclass = ABCMeta):
            @abstractmethod
            def 方法(self):
                pass
        如果一个类中包含了抽象方法. 那么这个类一定是一个抽象类
        一个抽象类中可以包含正常的方法

        接口: 接口中所有的方法都是抽象方法

        子类必须重写父类中的抽象方法. 否则子类也是一个抽象类
'''
View Code


# 异常处理  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("有误")  # 打印是给客户看的
View Code

 

 

# 日志(固定套路,用时照搬):
# 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, "我什么都不是")
View Code
1 # 例子,接上面
2 import traceback
3 try:
4     print(1/0)
5 except Exception:
6     logging.error(traceback.format_exc()) # 用法
7     print("出错了")
View Code

 

# 把⽇志⽂件分开 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系统')

 

 

 





 

posted @ 2018-11-13 21:08  刹那灯火明  阅读(207)  评论(0编辑  收藏  举报