day019类的约束,异常处理,日志

本节主要内容

1.类的约束(重点掌握)
2.异常处理及自定义异常
3.日志

一、类的约束(两种约束方法)

1.抛出异常
2.抽象类(跟其他语言相似)

1、抛出异常

抛出 Implemented,
class 父类名:  # 写个父类让子类继承
    def 方法名():  # 强制子类做某事
        raise NotImplementedError("子类未实现xxx功能") # 报错抛异常

fe:具体写法

# 约束的方法一: 抛异常
# 一般由项目经理(级别高的人)写约束

# 先写个约束的父类,子类继承父类,未覆盖父类的方法,就会抛异常
class Base:
    def login(self):        # 强制子类做某事
        raise NotImplementedError("子类没有实现login功能")  # 报错,抛异常

# 1.普通登录,
class Normal(Base):
    def login(self):
        print("这是普通用户登录")

# 2.吧务登录
class Member(Base):
    def login(self):
        print("这是吧务登录")

# 管理员登录
class Admin(Base):
    def denglu(self): # 子类没有覆盖父类的方法,会报错,你没有实现父类要求的功能(方法)
        print("这是管理员登录")

# 项目经理的总入口
def test(obj):
    obj.login()

a = Admin()
test(a)

2、抽象类

语法:
from abc improt ABCMeta, abstractmethod
class 抽象类名(metaclass = ABCMeta):  # 抽象类
    @abstractmethod
    def 方法(self): pass # 抽象方法

class Foo(Base):
    def 方法(self):  # 子类必须重写父类的抽象方法,否则子类也是抽象类
        pass

1、相关结论

1.子类必须重写父类的抽象方法,否则子类也是抽象类
2.抽象类不能创建对象
3.有抽象方法的类,就是抽象类
4.抽象类可以有普通方法
5.接口:接口所有方法都是抽象方法,(引用其他语言,python自己没有定义这一条)

fe:

from abc import ABCMeta, abstractmethod  # 引入抽象模块

class Animal(metaclass = ABCMeta): # 抽象类
    @abstractmethod  # 抽象方法
    def chi(self):  # 抽象的概念
        pass

class Cat(Animal):  # 子类
    def chi(self):   # 子类对抽象的内容给出具体的实现 . 重写
        print("猫用嘴吃,")

c = Cat()
c.chi()

a = Animal()   # 报错,抽象类不能创建对象(不能实例化对象)

二、异常处理及自定义异常

由python解释器来调用代码. 出现了错误. 系统会自动的产生一个叫异常的对象.
系统会尝试着把错误返回给调用方. 过程被称为:抛异常
我们通过try...except 可以吧系统产生的这个错误获取到. 过程叫捕获异常
我们对异常进行处理,返回让用户看的懂的异常信息
自己也在这个过程中,用improt traceback 获得堆栈信息(给程序员排错用的)

1、异常处理的写法

1.只对异常处理,不获取堆栈信息

try:
    xxxx
except 错误名称 as 别名:
    出现错误的时候. 要干什么...
except 错误名称 as 别名:
    出现错误的是偶. 要干什么
....
except Exception as e: # 所有错误的根
    出现的所有的错误. 我都可以这样处理
else: # 很少用到
    不出错的时候执行这里的代码
finally:
    结束. 收尾工作

2.对异常处理,并获取堆栈信息

import traceback
try:
    # 尝试执行的代码
except Exception as e:
    # 出了错之后要做什么
    traceback.format_exc() # 获取堆栈信息(错误信息)

fe1:第一种处理

try:
    print(1/0) #  0不能做除数   ZeroDivisionError: division by zero
except ZeroDivisionError as z:  # 拦截ZeroDivisionError,处理后返回给客户
    print("错了. 除数不能为0")

fe2:第二种处理

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, "胡辣汤")) # 加上异常的处理
except Exception as e:
    # 获取到错误信息. 我们需要访问堆栈信息
    print(traceback.format_exc()) # 获取堆栈信息
    print("出现了错误")

2、自定义异常

我们在自定义会出现的错误:
因为python中没有给出具体的记录, 慎用. 名字一定要符合规范

1、写法

class GenderException(Exception):   # 自定义错误名字,继承父类Exception,除了名字以外都是父类中的Exception
    pass

fe:自定义的示例

class GenderException(Exception):
    pass

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

    #  洗澡 -> 男的进男浴室
    def goto_nan_yushi(self):
        if self.gender != "男":
            raise GenderException("性别不对") # 除了名字以外都是父类中的Exception
        else:
            print("欢迎光临.")
try:
    p2 = Person("wusir", "女")   # 报错了就不在执行下面的内容了
    p2.goto_nan_yushi()
    p1 = Person("alex", "男")
    p1.goto_nan_yushi()
except GenderException as e:
    print("你去男澡堂子干嘛?")
except Exception as e:
    print("其他错误")

三、日志

日志一般一个公司只用一套,拿来知道要修改什么位置的信息就行,
不需要记,不需要写,知道原理,会调用就行

1、在Python创建日志系统

1. 导入logging模块.
2. 简单配置⼀下logging
3. 出现异常的时候(except). 向⽇志⾥写错误信息.

2、只能写到一个日志文件的日志方法

import logging
# filename: ⽂件名
# format: 数据的格式化输出. 最终在⽇志⽂件中的样⼦
# 时间-名称-级别-模块: 错误信息
# datefmt: 时间的格式
# level: 错误的级别权重, 当错误的级别权重⼤于等于leval的时候才会写⼊⽂件
logging.basicConfig(filename='x1.log',
     format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
     datefmt='%Y-%m-%d %H:%M:%S',
level=0)
# 当前配置表示 0以上的分数会被写⼊⽂件
# CRITICAL = 50 # 系统崩溃,一般程序员不设置这个等级
# FATAL = CRITICAL
# ERROR = 40  # 错误,项目或产品上线后,一般程序员设置这个等级
# WARNING = 30
# WARN = WARNING  # 警告,用户不按正常操作引起,
# INFO = 20  # 信息
# DEBUG = 10  # 测试的时候
# NOTSET = 0  # 获取所有信息
logging.critical("我是critical") # 50分. 最贵的
logging.error("我是error") # 40分
logging.warning("我是warning")
logging.info("我是info")
logging.debug("我是debug")
logging.log(1, "我什么都不是")

import traceback
try:
    print(1/0)
except Exception:
    logging.error(traceback.format_exc()) # 用法
    print("出错了")

3、分开记录日志的方法

一个大项目,分两个子系统,需要分开记录,我们需要借助文件助手(FileHandler)
import logging
# 创建⼀个操作⽇志的对象logger(依赖FileHandler)
#                       open()
file_handler = logging.FileHandler('zuo.log', 'a', encoding='utf-8')
file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))
logger1 = logging.Logger('qq', level=20)
logger1.addHandler(file_handler) # 把文件助手和日志对象绑定
logger1.error('我是A系统出错了') # 记录日志


# 再创建⼀个操作⽇志的对象logger(依赖FileHandler)
file_handler2 = logging.FileHandler('you.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=20)
logger2.addHandler(file_handler2)


import traceback
try:
    print(1/0)
except Exception:
    logger2.critical(traceback.format_exc())
    print("出错了. 请联系管理员")
print("程序继续知悉个")
原文地址:https://www.cnblogs.com/yipianshuying/p/9947450.html