day26 python约束 自定义异常 hashlib模块 logging模块

day26 python约束 自定义异常 hashlib模块 logging模块 
 
一.约束
    1.如何定规则: 体现在代码里的规则, 必须要遵守的
        父类中编写要约束的函数, raise NotImplementedErrot() 错误: 连参数也可一同约束 (implement 实现)
class BaseMessage:                          #这个类用于约束派生类, 保证派生类中必须编写send(), 不然执行可能报错
    def send(self):
        '''
        必须继承BaseMessage之后, 必须编写send方法, 用于完成具体的业务逻辑
        :return:
        '''
        raise NotImplementedError(".send() must be overridden")
def func(arg):
    '''
    报警通知的功能
    :param arg:
    :return:
    '''
    arg.send()                                #如果让三个人分别写一个类, 那么类里面必须要有send方法
class Email(BaseMessage):
    def send(self):
        print('send email')
    def f1(self):
        pass
class Wechat(BaseMessage):
    def send(self):
        print('send email')
    def f2(self):
        pass
class Msg(BaseMessage):
    def send(self):
        print('send message')
    def f3(self):
        pass
    2.源码的约束就是这么写的
#pip3 install djangorestframework
# from rest_framework.authentication import SessionAuthentication
# from rest_framework.authentication import RemoteUserAuthentication
# from rest_framework.authentication import TokenAuthentication
#上面三个类都是继承了下面的类
class BaseAuthentication:
    def authenticate(self, request):
        raise NotImplementedError(".authenticate() must be overridden")     #未实现错误: 这个方法必须被重写
    3.示例
class Foo:
    def f1(self,name):
        raise NotImplementedError('.f1() must be overridden')
class Bar(Foo):
    def f1(self,name):
        print('in bar')
obj = Bar()
obj.f1('bajie')
    4.其他语言中的接口和类, 与python对比
python中没有接口,只有类
    类的编写: class 自定义类名:
        pass 
    关于多继承: 
        允许 
    关于约束:
              
 
java和c#中既有接口,也有类
    类的编写: class 自定义类名:
        pass
    接口的编写: interface 自定义接口名:
        pass
    接口的用途:
        接口中不允许在方法内部写代码,主要用于约束它的子类,必须实现接口中的所有方法
    关于多继承: 
        不允许
        但是可以继承多个接口, 这里的继承叫做实现
    关于约束: (伪代码)
        使用抽象类和抽象方法也可做约束, 约束子类中,必须实现抽象类中的抽象方法(abstract 抽象)
        abstract class 自定义类名:
            def f1()    
            abstract def f2()
         
    5.类的分类
        分为普通类和抽象类
    6.python的另外一种约束:
        还支持抽象类和抽象方法进行约束(了解, 基本不用)
from abc import ABCMeta,abstractmethod
class Base(metaclass=ABCMeta):                              #定义抽象类
    def f1(self):                                           #可以定义普通方法
        print(123)
    @abstractmethod                                         #定义抽象方法
    def f2(self):
        pass
class Foo(Base):
    def f2(self):                                           #如果没有抽象父类的,抽象方法,实例化的时候会报错
        print(666)
    7.总结: 
    1.什么是接口?以及作用
        接口是一种数据类型, 主要用于约束派生类中必须实现指定的方法
        python中不存在, 而java和c#中是存在的
    2.python 中是用什么来约束呢
        抽象类和抽象方法, 编写比较麻烦
        人为主动抛出异常, 编写简单明了
    3.抛出异常的异常错误类型, 是否可以用其他异常
        不专业: raise Exception(".send() must be overridden")
        专业: raise NotImplementError(".send() must be orverridden")
    4.以后看代码时, 揣摩心思
    5.应用场景
        多个类, 内部都必须有某些方法时, 需要使用基类+异常约束
 
二.异常处理最后一招: 自定义异常
    1.方式一: 一个一个条件判断, 返回异常信息
import os
def func(path,prev):
    '''
    去path路径的文件中, 找到前缀为prev的一行数据, 获取数据并返回给调用者
        1000,成功
        1001,文件不存在
        1002,关键字为空
        1003,未知错误
    :return:
    '''
    response = {'code':1000, 'data':None}
    try:
        if not os.path.exists(path):
            response['code'] = 1001
            response['data'] = '文件不存在'
            return response
        if not prev:
            response['code'] = 1002
            response['data'] = '关键字为空'
            return response
        a = 1
        pass
    except Exception as e:
        response['code'] = 1003
        response['data'] = '未知错误'
        return response
    return a
def show():
    return 8
def run():
    v1 = func()
    v2 = show()
    2.方式二: 自定义异常: 
        2.1.自定义异常类
        2.2.if后主动raise自定义继承Exception的类
        2.3.然后再捕获自定义异常,返回给用户具体的异常信息
import os
class ExistsError(Exception):                              #1.自定义异常类: 继承所有异常类的基类Exception
    pass
class KeyInvalidError(Exception):
    pass
def func(path,prev):
    response = {'code':1000, 'data':None}
    try:
        if not os.path.exists(path):
            raise ExistsError()                            #2.主动抛出异常: 抛出自定义异常类, 下面就可以捕获你自定义的异常
        if not prev:
            raise KeyInvalidError()
        a = 1
        pass
    except ExistsError as e:                               #3.捕获自定义的异常: 在自定义异常里, 定义字典的code和data, 将具体的异常信息返回给用户
        response['code'] = 1001
        response['data'] = '文件不存在'
        return response
    except KeyInvalidError as e:
        response['code'] = 1002
        response['data'] = '关键字为空'
        return response
    except Exception as e:
        response['code'] = 1003
        response['data'] = '未知错误'
        return response
    return a
def show():
    return 8
def run():
    v1 = func()
    v2 = show()
    3.异常体现的就是封装
class MyException(Exception):
    def __init__(self, code, msg):
        self.code = code
        self.msg = msg
try:
    raise MyException(1000,'操作异常')
except MyException as e:                           #e 是实例化异常类的对象
    print(e.code, e.msg)                           #可以调用类中的成员
except KeyError as e:
    print(e,1111)
except Exception as e:
    print(e,2222)
 
三.hashlib模块: 用于加密的
    1.对'字符串'进行加密, 实际是bytes类型的    (hex 十六进制, digest 摘要)
import hashlib
 
obj = hashlib.md5()                                 #实例化对象
obj.update('bajie'.encode('utf-8'))                 #写入要加密的字节
rst = obj.hexdigest()                               #获取密文(结果是没法反解的:说的是算法)(可以反解: 当你的字符串-密文的库足够强大时, 可以撞库出来)
print(rst)
    2.如何防止撞库: 加盐
import hashlib
obj = hashlib.md5(b'secretbajie')                   #加的盐, 也是字节码
obj.update('bajie'.encode('utf-8'))
rst = obj.hexdigest()
print(rst)
    3.hashlibd 的应用
        如何解密: 解不了,可以密文和密文之间比较
import hashlib
def md5(pwd):
    obj = hashlib.md5(b'secretbajie')            
    obj.update(pwd.encode('utf-8'))
    rst = obj.hexdigest()
    return rst
usr = input('name: ')
pwd = input('passwd: ')
 
if usr == 'bajie' and md5(pwd) == '837a5f2beb5ec1330e0f0aeadd8a184a':
    print('successful')
    4.再谈hashlib
        md5, sha256, sha512 名字不同, 加密的复杂度不一样: md5是32位的; 256, 512比32位更复杂, 更安全
        但性能和安全要有取舍, 一般md5就够用了
 
    5.当加密的内容比较多, 可多次update()进行追加, 结果和一次update的摘要是一样的
import hashlib
def md5(filename):
    md5 = hashlib.md5('bajieaishuishui')
    with open(filename,mode='r',encoding='utf-8') as f:
        for line in f:
            md5.update(line.encode('utf-8'))
        else:
            return md5.hexdigest()
print(md5('ssh_server.py'))
 
四.logging模块
    1为什么要有日志? 给开发人员看的, 用于排查错误.
        logging模块做了什么? 会帮你处理并发, 不会出错, 支持线程安全, 默认日志文件是追加写
import logging
 
logger = logging.basicConfig(
                filename='log.txt',
                format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',           #日志里每条记录的格式,前4个不用传.模块自己会传:
                datefmt = '%Y-%m-%d %H:%M:%S',
                level=10,)                                                                           #限制下面的记日志的动作, 只有 >= 这个级别的才记录  #默认是 30
 
logging.debug('this test line is mydebug')         #10     #把 %(message)s 的日志记录写到日志文件里  #测试环境,
logging.info('this test line is myinfo')           #20     #把 %(message)s 的日志记录写到日志文件里  #正常信息
logging.warning('this test line is mywarning')     #30     #把 %(message)s 的日志记录写到日志文件里  #警告: 只是警告
logging.error('this test line is myerror')         #40     #把 %(message)s 的日志记录写到日志文件里  #错了哥
logging.critical('this test line is mycritical')   #50     #把 %(message)s 的日志记录写到日志文件里  #严重了哥
 
logging.log(20, 'this test line is mylog')         #可以用上面模块自带的级别, 也可以自己写, 传入对应的数字,(和上面的五个对应的一致)
    2.应用1
import logging
def func():
    try:
        a = a + 1
    except Exception as e:
        print(e)                                    #print(对象), 实际执行的是 __str__()方法
        logging.error(e)                            # e 是这个类的对象
        logging.error(e.__str__())                  #专业点, 就是把e.__str__() 写到日志
func()
    3.应用, 如何把更详细的信息写到日志里(比如traceback 回溯信息)
import traceback
def func():
    try:
        name = bajie
    except Exception as e:
        rst = traceback.format_exc()                 #拿到trackback信息: 当前错误的堆栈信息
        logging.error(rst)                           #写到日志
func()
    4.日志的文件个数, 如何把日志记到不同的文件
        4.1.默认只能初始化设置一个日志文件
import logging
logger1 = logging.basicConfig(
                filename='log1.txt',
                format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
                datefmt = '%Y-%m-%d %H:%M:%S',
                level=10,)
logging.error('logging1 . ')                          #正常写日志
 
logger2 = logging.basicConfig(                        #logger2 没有生效, 配置不能二次初始化设置
                filename='log2.txt',
                format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
                datefmt = '%Y-%m-%d %H:%M:%S',
                level=10,)
logging.error('logging2 . ')                          #第二次配置没有生效, 这条日志写到了第一个配置时的日志文件中
        4.2.把日志写入到多个不同的文件, 需要自己定义自己搞
import logging
 
f1 = logging.FileHandler('log1.txt','a',encoding='utf-8')                                                            #1.搞个文件句柄
f1.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s"))           #2.搞个日志格式
logger1 = logging.Logger('s1',level=logging.ERROR)                                                                   #3.搞个日志级别
logger1.addHandler(f1)                                                                                               #4.把句柄交给logger1
 
logger1.error('my name is error, logger1')                                                                           #5.写日志
 
f2 = logging.FileHandler('log2.txt','a',encoding='utf-8')
f2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s"))
logger2 = logging.Logger('s2',level=logging.ERROR)
logger2.addHandler(f2)
 
logger2.info('my name is error, logger2')
logger2.error('my name is error, logger2')
logger2.critical('my name is critical, logger2')
 
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/aiaii/p/12217070.html