20.异常 加密 约束

1.

1.昨日内容回顾
1.issnbclass ,type,isinstance
issubclass:判断xxx是xxxx的子类么
type:精准的返回对象的类型
isinstance:判断xxx对象是否是xxx类型的

2.函数和方法
在类外面 都是函数
在类里面
1.实例方法 对象.方法 方法 类名方法 函数
2.静态方法 :都是函数
3.类方法 都是方法

判断的时候
引入types模块中的FunctionType和MethodType 来判断是函数还是方法
isinstance()
3.反射
1.hasattr(obj,str)判断对象中是否包含xxxx(str)
2.getattr(obj,str)从对象中获取xxx(str)
3.setattr(obj,str,value)把对象中的str设置成value
4.delattr(obj,str)从对象中删除xxx(str)

二.今日主要内容
异常处理(处理,抛出异常,自定义异常)
1.产生异常, raise异常类(),抛出异常
2 处理异常
try:
xxxxx #尝试执行的代码
expect 异常类 as变量: #出现错误的时候,捕获到异常
xxxx #处理异常
3.自定义异常
继承 Exception
4.堆栈信息
import traceback
tracaback.formal_exc() 获取堆栈信息
约束(难)
约束是对子类进行的约束
一.通过抛异常(简单)
在父类中给出一个方法,这个方法中什么都不写,就抛异常。NoImplementError()
在子类中把上述的方法进行重写
重写:子类重新定义父类中的方法

二.抽象类和抽象方法
接口:类中都是抽象方法
from abc import ABCMeta,abstractmethod

抽象方法:抽象方法不用给出方法体,写个pass就行了
抽象类:
语法:类(metaclass = ABCMeta )
概念:如果类中包含了抽象方法,这个类一定是抽象类
特点:抽象类一般不创建对象
抽象类中可以存在正常方法

可以约束子类必须实现抽象方法
Md5加密
Md5加密 :不可逆
引入模块 hashlib
1.创建md5对象
2.把加密信息交给md5对象
3.获取密文
日志处理
(重要,简单)
引入logging模块
简单配置即可 (basicConfig 单一日志文件 fileHandle 文件助手可以实现文件操作)
日志级别:
CRITICAL 最高的
error 40
warn 30
info 20
debug = 10
异常处理
异常和抛出异常
1.异常,异常是在程序运行过程中产生的错误
def chu(a,b):
    return a/b
ret = chu(10,0)#如果这里出现了错误,异常 系统会把这个错误抛出,抛给调用方
print(ret)

# def chu(a,b):
#     return a/b
# try:
#     ret = chu(10,0)
#     print(ret)
# except Exception as e:
#     print('除数不能是0')
#尝试去执行try 里面的代码,出现了错误,就执行except后面的代码
'''原理就是系统产生错误的异常向外抛的时候被except拦截,并赋值
给e。Exception是所有异常的基类,也就是异常的根,所有的异常都可以叫
Exception,比较笼统,所以可以写更多的except'''

捕获异常和处理异常保护程序能够正常运行

捕获异常

def chu(a,b):
    try:
        ret = a/b
        return ret
    except ZeroDivisionError as e:
        print(e)
        print('出错了,0不能是除数')
    except FileNotFoundError as e:
        print('出错了,0不能是除数')
    except StopIteration as e:
        print('出错了,0不能是除数')
    except Exception as e:
        print('除数不能是0')
ret = chu(10,0)
print(ret)
出现哪个错误就会被相应的except捕获,如果都没出现就会被最后一个Exception
try :
    '''代码操作'''
except Exception as e:
    '''异常的父类,可以捕获所有的异常'''
else:
    '''保护不抛出异常的代码,当try中无异常的时候执行'''
finally:
    '''最后执行的文件'''


在处理异常的过程中会出现一些条件上的不对等,根本不符合
代码逻辑,如何返回给调用方

 

抛出异常
def add(a,b):
'''传递两个整数,返回代码的和'''
if type(a)!= int and type(b)!= int:
#当程序运行到这个时候,整个函数的调用会被中断。】
# 并向外抛出一个异常
raise Exception('不是整数,我的程序无法帮你搞定')
return a+b
# print(add(1,3))
print(add('nihao','我叫大佬'))
如果调用方不处理异常,产生的错误将会继续向外抛,最后就抛给了用户
如果调用方处理了异常,那么错误就不会传给用户,程序可以正常运行


处理异常

def add(a,b):
    '''传递两个整数,返回代码的和'''
    if type(a)!= int and type(b)!= int:
        #当程序运行到这个时候,整个函数的调用会被中断。】
        # 并向外抛出一个异常
        raise Exception('不是整数,我的程序无法帮你搞定')
    return a+b
# print(add(1,3))
print(add('nihao','我叫大佬'))
# 如果调用方不处理异常,产生的错误将会继续向外抛,最后就抛给了用户
# 如果调用方处理了异常,那么错误就不会传给用户,程序可以正常运行
try :
    add('nihao','我叫大佬')
except Exception as e:
    print('有错误,自己处理')

 

在python中可以自定义异常

 自定义异常非常简单,只要类继承了    Exception,类就是一个异常类】
# class GenderError(Exception):
#     pass
# class Person:
#     def __init__(self,name,gender):
#         self.nmae = name
#         self.gender = gender
# def nan_zao_tang_xi_zao(person):
#     if person.gender != '男':
#         raise GenderError('这里不能有女生,男孩子会害羞哒')
#     else:
#         pass
# p1 = Person('alex','不详')
# nan_zao_tang_xi_zao(p1)会抛出一个异常GenderError

# 3处理异常
# try:
#     nan_zao_tang_xi_zao(p1)
# except GenderError as g:
#     print(g)
#  这样出现的问题就是调试出来看不到错误源

这样的话调用方看到的是有错误,可是根本不知道错误源

#  这样出现的问题就是调试出来看不到错误源
# 这样的话就需要引入另一个模块  traceback
import traceback
# 继承Exception,那么这个类就是一个异常类
class GenderError(Exception):
    pass
class Person:
    def __init__(self,name,gender):
        self.nmae = name
        self.gender = gender
def nan_zao_tang_xi_zao(person):
    if person.gender != '':
        raise GenderError('这里不能有女生,男孩子会害羞哒')
    else:
        pass
p1 = Person('alex','不详')
# nan_zao_tang_xi_zao(p1)#会抛出一个异常GenderError

# 3处理异常
try:
    nan_zao_tang_xi_zao(p1)
except GenderError as g:
    val = traceback.format_exc()#获取到堆栈信息
#     #这样的话测试代码的时候把堆栈信息打印出来,到了线上的生产环境
#     # 把这个堆栈去掉
#     print(g)
#     print(val)

约束

调用代码出现的因为名称不同不能调用的示例

# class Normal:
#     def login(self):
#         pass  #普通登录
# class Member:
#     def denglu(self):
#         pass #会员登录
# class Admin:
#     def login(self):
#         pass#王五登陆
# # 3三种不同的方式,假如是三个人写的
# def login(obj):
#     print('准备验证码')
#     obj.login()
#     print('进入主页')
# n = Normal()
# m = Member()
# a = Admin()
# login(n)
# login(m)
# login(a)
# 这样的话调用不了其中的一个代码,这样的话需要通过约束程序的结构

解决方案

# 也就是说,一开始就需要把功能定义好,
# 两种方法来解决这个问题
'''1.提取父类,然后在父类中定义好方法,在这个方法中什么都不用干,就抛一个
异常,这样的话所有的子类都必须重写这个方法,否则访问就会报错。
2.使用元类来描述父类,在元类中给出一个抽象对象,这样的话子类就不得不
给出抽象方法的具体实现,也可以取到约束的效果'''

第一种解决方案
# 第一种解决方案
# 提取一个父类,在父类中给吃一个方法,并且在方法中不给出任何代码,直接抛异常
class Base:
    def login(self):
        raise NotImplementedError('你没有实现我要求的登录方法login()')
class Normal(Base):
    def login(self):
        pass  #普通登录
class Member(Base):
    def denglu(self):
        pass #会员登录
class Admin(Base):
    def login(self):
        pass#王五

def login(obj):
    print('准备验证码')
    obj.login()
    print('进入主页')
n = Normal()
m = Member()
a = Admin()
login(n)
login(m)
login(a)

# 这样的话会很容易的知道程序出的错误是什么错误,容易改

第二种方案

# 写抽象类和抽象方法
# 需要在python中编写一个抽象类比较麻烦,需要引入abc模块中的ABCMeta和absstractmethod 这两个内容
# from abc import ABCMeta,abstractmethod
# #类中包含了抽象方法,那么这个类就是抽象类
# class Animal(metaclass = ABCMeta): #在父类中写出metaclass= xxx
# # 抽象类, 类中存在抽象方法, 类一定是抽象类
#     @abstractmethod  # 抽象方法
#     def chi(self): # 抽象的概念.
#         pass
#     def haha(self):
#         print("娃哈哈")
# class Cat(Animal): # 子类必须实现父类中的抽象方法.
#     def chi(self):  # 具体的实现
#         print("猫爱吃鱼")
#
# c = Cat()
# c.chi()
#
# from abc import ABCMeta,abstractmethod
# class Base(metaclass=ABCMeta):
#     @abstractmethod
#     def login(self):
#         pass
# class Normal(Base):
#     def login(self):
#         pass  #普通登录
# class Member(Base):
#     def denglu(self):
#         pass #会员登录
# class Admin(Base):
#     def login(self):
#         pass#王五
#
# def login(obj):
#     print('准备验证码')
#     obj.login()
#     print('进入主页')
# n = Normal()
# m = Member()
# a = Admin()
# login(n)
# login(m)
# login(a)


# 会报错,约束其实就是父类对子类的约束,子类必须要写xxx方法,
# 在Python中约束的方式和方法有两种

# 1.使用抽象类和抽象方法,该方法来源于Java和c#,使用频率较少
#2.使用人为抛出异常的方案,并且尽量抛出的是NotimplementError
# 这样错误比较明显

md5加密

import hashlib
obj =hashlib.md5()
obj.update('alex'.encode('utf-8'))
miwen = obj.hexdigest()
print(miwen)

# 这样的密文会被破解,不安全

import hashlib
obj =hashlib.md5(b'fjeifjeigjeigjejejgejjjg')  #创建一个MD5对象
obj.update('alex'.encode('utf-8'))#加密的必须是字节  把要加密的对象传给md5
miwen = obj.hexdigest()  #获取密文
print(miwen)
#这样的话就不能被破解
# import hashlib
# def my_md5(val):
# obj =hashlib.md5(b'flkjsdalkfjklasdjfklasjkflasdjklfasdjflkadsj')
# obj.update(val.encode('utf-8'))
# val = obj.hexdigest()
# return val
这个模块可以直接复制调用
只用修改val里面传进来的参数,或者修改字符串 但是同一个文件不要修改字符串

实例

import hashlib
def my_md5(val):
    obj =hashlib.md5(b'flkjsdalkfjklasdjfklasjkflasdjklfasdjflkadsj')
    obj.update(val.encode('utf-8'))
    val = obj.hexdigest()
    return val

# 注册的时候. 用md5进行加密. 存储的是加密后的密文
username = input("请输入用户名")
password = input("请输入密码")
cun = my_md5(password)
print(cun) # alex 26adff81aa6778d26999b95ddc0e50b2
if username == "alex" and my_md5(password) == "26adff81aa6778d26999b95ddc0e50b2":
    print("登录成功")
else:
    print("登录失败")

 

文件日志处理

# 写程序的时候,可能总会出现bug,这些问题一般在测试的时候都要给处理掉,但是有些bug是不一定显示出来的
# 可是还是要在测试的时候解决它
# 需要给所写的程序准备一套日志系统,出现错误的时候,去日志系统里查看,看哪里出现了问题,
# 这样在解决bug的时候就更容易
如何在python中创建日志文档
如何在python中创建日志系统
1.导入logging模块
2.简单配置logging
3.出现异常的时候(except)。向日志里写错误信息
import logging
logging.basicConfig(filename='app.log',
                    format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    level=0)

设置好就可以写日志
logging.error('你在干什么')
# level 设置级别. 当你的信息的级别>=level的时候才会写入日志文件, 默认30
#filename 文件名
#format  数据的格式化输出,最后在日志中呈现出来的样子
    # 时间——名称——级别——模块:错误信息
#datefmt 时间的格式
#leval  错误的级别权重,当错误的级别权重大于等于leval的时候才会写入文件
# 在源码中展示的信息


# CRITICAL = 50
# FATAL = CRITICAL
# ERROR = 40
# WARNING = 30
# WARN = WARNING
# INFO = 20
# DEBUG = 10
# NOTSET = 0
logging.critical('我是critical')  #50
logging.ERROR ('我是ERROR ')
logging.WARNING('我是警告')
logging.INFO ('我是基本信息 ')
logging.DEBUG('我是调试')
logging.log(2,'我是自定义')   #自定义leval 的值

 

多系统文件多日志处理
如果系统要把日志文件分开,比如一个大项目,有两个子系统。name这两个
子系统要分开记录日志,方便调试
用上面的basicConfig是不行的,要借助文件助手(FileHander)来帮我们完成日志的分开记录
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=40)
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=40)
logger2.addHandler(file_handler2)
# 记录日志
logger2.error('我是B系统')
#

 

posted on 2018-10-16 23:26  小王子QAQ  阅读(41)  评论(0)    收藏  举报