面向对象---异常处理,约束,MD5加密,日志处理,
思维导图:
1.异常处理
首先说什么是异常处理,异常处理就是在程序运行过程中产生的错误,不正常,其实我们在之前的时候已经见过了很多了,只要一报错,就是异常处理
我们先拿其中一个举例子
def chufa(a,b) : try : ret = a / b return ret except ZeroDivisionError as e : print("出错了,0不可以是除数") #内部产生的所有异常都会被捕获,捕获的异常对象将交给e chufa(10,0) #division by zero
我们来讲一个故事,假设主人公褚熙他是我的小弟,有一天我叫他去给我打劫去,这时候用到try的时候就到了,后面就接着except打劫.意思就是你大胆的去做,不管你怎么着,我给你兜着打劫这个事情,但是换句话说,如果他小偷小摸的去便利店偷火腿,因为我说了,打劫的事情帮你兜着,但是我没有说偷东西这个事情我给你兜着,所以如果褚熙去偷火腿,这个事情就不行了,就会报错了.
所以说try..except是什么呢?尝试运行xxx代码,出现了错误,就执行except后面的代码,在这个过程中,当代码出现错误时候.系统会产生一个异常对象,然后这个异常会向外抛,被exppt拦截,并把接受到的异常对象赋值给e.那这里的e就是异常对象,那这里的Exception的子类对象.我们看到的ZeroDivisionError 其实就是Exceptiond 的子类,那这样写的好像有点问题,Exceptiond 表示所有的错误,太笼统了,所有的错误都会被认为是Exception,当写程序中出现多种错误的时候,就不好分类了,最好是出什么异常就用什么来处理,这样就更加合理了.所以在try....execpt语句中,还可以写更多的except
def func(): try : except ZeroDivisionError as e : print("出错了,0不可以是除数") #内部产生的所有异常都会被捕获,捕获的异常对象将交给e except FileExistsError as e : print("文件不存在") except Exception as e : print("其他错误")
解读:程序先执行操作,然后如果出错了会走except中的代码,如果不出错,执行else中的代码,不论出不出错,最后都是要执行finally中的语句,一般我们用try ... except就够用了,顶多加上finally.finally一般用来做收尾的工作.
上面的是异常处理,我们在执行代码的时候,如果出现了一些条件上不对等,根本不符合我的代码逻辑的,比如参数,我要求你传递一个数字,你给我一个字符串,那对不起,这样不对我们没有办法帮你处理,如果是这样的话,那我如何通知呢?
方案一:直接返回即可,我不管你了
方案二:抛出一个异常,告诉你,我不好惹,给我乖乖的回去
方案一,之前遇到这样的情况我们都会视而不见,直接绕过去,但是这样的写法并没有写起到警示作用,所以以后的代码中如果出现类似的问题,直接抛出一个错出去,那怎么抛? 我们要用到reise关键字
def add(a,b): ''' 计算两个整数的加法 :param a: :param b: :return: 返回a+b的值 ''' if type(a) != int or type(b) != int : raise TypeError("我这里只要int类型,不要别的类型") return a+b
如果调用方不处理异常,那产生的错误会继续想外抛,最后就抛给了用户
如果调用方处理异常,那么错误就不会给用户,程序也可以正常进行
try: add("胡辣汤","褚熙") except Exception as e : print("报错了,自己处理吧")
说这么多,异常也知道如何抛出和处理了,但是如果我们现在用python给的异常,如果你有一天你写的爱吗出现了一个无法用现在用的异常来解决问题,你该怎么办?
自定义异常:非常简单,只要你的类继承Exception 类,那么你的类就是一个异常类,就这么简单,比如你要写个猫咪的程序,这个时候来个狗,怎么办?是不是要抛出种类异常
import traceback #获取堆栈信息 class Cat(Exception):#Exception可以包括所有的错误 pass class Animal : def __init__(self,name,pin_zhong): self.name = name self.pin_zhong =pin_zhong def boSiCat(ani): if ani.pin_zhong != "cat" : raise Cat("不是猫的品种") else: pass p1 = Animal("小罗","dog") p2 = Animal("小哈","cat") try: boSiCat(p1) #__main__.Cat: 不是猫的品种 except Cat as e: print(e) val = traceback.format_exc()#报错就会抛出一个异常 print(val)
这样的话我们就可以收放自如,当测试代码的时候吧堆栈的信息打印出来,但当到了线上的生产环境的时候就把这个堆栈去掉即可.
四.MD5加密
md5是不可逆的加密算法,所以他是可靠的,并且安全,在Python中我们不需要手写这套算法,只需要引入一个hashlib的模块就可以搞定了加密工作
def my_mad(val): ''' 获取密文 :param val: 从用户获取的密码进行加密 :return: 返回加密后的密码 ''' obj = hashlib.md5(b"zhaoruixin") #创建一个md5对象 obj.update(val.encode("utf-8"))#把加密内容给md5 必须是字节,所以需要解码 val = obj.hexdigest()#调用模块 return val
所以. 以后存密码就不要存明文了. 要存密码. 安全, 并且. 这里加的盐不能改来改去的.
否则, 整套密码就都乱了
def my_md5(val): ''' 获取密文 :param val: 从用户获取的密码进行加密 :return: 返回加密后的密码 ''' obj = hashlib.md5(b"zhaoruixin") #创建一个md5对象 obj.update(val.encode("utf-8"))#把加密内容给md5 必须是字节,所以需要解码 val = obj.hexdigest()#调用模块 return val username = input("请输入你的用户名")#赵瑞鑫 pwd = input("请输入密码")#521 cun = my_md5(pwd) print(cun)#a1a67811e0840823c6c7203669113ccd #测试 if username =="赵瑞鑫" and my_md5(pwd) == "a1a67811e0840823c6c7203669113ccd": print("登录成功") else: print("用户名或密码错误")
五,日志
首先你要知道在编写的时候都会出现一些问题或者bug,这些问题或者bug都会在测试的时候处理掉,但是多多少少会有些意向不到的意外状况,那这个时候,我们是不知道哪里出现了问题,因为很多bug都不是必现的,测试的时候一定能测出来,最头痛的是这样的不必现bug.在这里跑没问题.到了用户那里,就会出问题,怎么办?所以给软件准备一套日志系统,当出现错误的时候,我们可以去日志系统去查看,看是哪里出现了问题,那么如何创建这个日志系统呐 ?
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 = 40) #level 设置级别,当你的信息级别 >= level的时候才会写入日志文件,默认是30 CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 # 写日志 logging.critical("我是critical")#最严重的错误 logging.error("我是error")#第二严重的错误 logging.warning("我是警告") logging.info("我是基本信息") logging.debug("我是调试") logging.log(2, "我是自定义")
多个日志文件操作
# 多文件日志处理 # 创建⼀个操作⽇志的对象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系统')