约束、自定义异常、hashlib模块、logging日志模块
一、约束(重要***)
1、首先我们来说一下java和c#中的一些知识,学过java的人应该知道,java中除了有类和对象之外,还有接口类型,java规定,接口中不允许在方法内部写代码,只能约束继承它的类必须实现接口中定义的所有方法,为了便于理解,我们用python和java混合语法来写一下java中的接口,如下示例:
interface IFoo: # 定义接口Ifoo,接口内部的方法不能写任何功能代码
def f1(self, x1):
pass
def f2(self, x1):
pass interface IBar: # 定义接口Ibar,接口内部的方法不能写任何功能代码
def f3(self, x1):
pass
def f4(self, x1):
pass class Foo(IFoo, IBar): # 实现了2个接口,不叫继承,java、c#不支持多继承
def f1(self, x1):
pass
def f2(self, x1):
pass
def f3(self, x1):
pass
def f4(self, x1):
pass
注意:java、c#是编译型语言,如果类Foo中没有实现其2个接口的所有方法,则无法编译
java和c#知识
除了接口以外,java中还有抽象方法、抽象类的概念:抽象类可以约束继承它的派生类必须实现它其中的抽象方法,如下示例:
abstract class Foo: # 定义一个抽象类
def f1(self):
print(1, 3, 4) # 定义抽象方法,用来约束,内部不能写功能代码
abstract def f2(self):
pass class Bar(Foo):
def f2(self):
print('')
# 抽象类Foo的派生类Bar必须实现Foo类中的抽象方法,否则无法编译
# 其他非抽象方法可以正常写功能代码以供派生类调用
java中的抽象方法、抽象类
综上可解决问题:什么是接口以及它的作用?
接口是一种数据类型,主要用于约束派生类中必须实现指定的方法,java和c#中存在。
2、介绍到这里你可能也在想python中有没有接口呢?答案是没有!那python使用什么来约束呢?如下:
# ### 示例一:python中的使用抽象方法、抽象类约束
from abc import ABCMeta,abstractmethod class Base(metaclass=ABCMeta): # 抽象类
def f1(self):
print(123) @abstractmethod
def f2(self): # 抽象方法,方法上方加@abstractmethod
pass class Foo(Base):
# Foo中必须重写父类Base中的抽象方法,否则程序无法执行
def f2(self):
print(666)
# ### 示例二:人为主动抛出异常来约束
class BaseMessage(object):
def send(self,x1):
"""
必须继承BaseMessage,然后其中必须编写send方法。用于完成具体业务逻辑。
"""
raise NotImplementedError(".send() 必须被重写.") class Email(BaseMessage):
def send(self,x1):
print('发送邮件') obj = Email()
obj.send(1)
总结:python中有两种方法来约束:
1)抽象类+抽象方法,编写上比较麻烦,不推荐;
2)人为主动抛出异常,源码也是这样写的,推荐;
注意:抛出异常也可以用raise Exception(),但是推荐使用raise NotImplementedError()。
3、约束的应用场景:有多个类,内部都必须有某些方法时,需要使用基类+异常进行约束。如下示例:
# ### 应用示例:学员管理系统
class IBase:
def login(self):
raise NotImplementedError(".send() 必须被重写.") class Student:
def login(self):
pass
def score(self):
pass class Teacher:
def login(self):
pass
def exam(self):
pass class Manager:
def login(self):
pass
def func(self):
pass
约束的应用场景
二、自定义异常(***)
以前的处理异常的写法,如下示例:
# ### 示例一:
import os
def func(path,prev):
"""
去path路径的文件中,找到前缀为prev的一行数据,获取数据并返回给调用者。
1000,成功
1001,文件不存在
1002,关键字为空
1003,未知错误
...
"""
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
pass # 这里是正常的业务逻辑代码
except Exception as e:
response['code'] = 1003
response['data'] = '未知错误'
return response
以前的写法
学完面向对象后,我们可以自定义异常,好处是try部分的功能代码逻辑更加清晰,如下示例:
# ### 示例二:自定义异常
import os class ExistsError(Exception):
pass class KeyInvalidError(Exception):
pass def new_func(path,prev):
"""
去path路径的文件中,找到前缀为prev的一行数据,获取数据并返回给调用者。
1000,成功
1001,文件不存在
1002,关键字为空
1003,未知错误
...
"""
response = {'code':1000,'data':None}
try:
if not os.path.exists(path):
raise ExistsError()
if not prev:
raise KeyInvalidError()
pass # 这里是正常的业务逻辑代码
except ExistsError as e:
response['code'] = 1001
response['data'] = '文件不存在'
except KeyInvalidError as e:
response['code'] = 1002
response['data'] = '关键字为空'
except Exception as e:
response['code'] = 1003
response['data'] = '未知错误'
return response
现在的写法
总结:自定义异常的知识点有三个,如下示例:
# 知识点:如何自定义异常类?
class MyException(Exception): # Exception是所有异常类的基类
def __init__(self, code, msg):
self.code = code
self.msg = msg
try:
raise MyException(1000, '操作异常') # 知识点:主动抛出异常
except KeyError as obj:
print(obj, 1111)
except MyException as obj: # 知识点:捕获自定义的异常
print(obj, 2222)
except Exception as obj:
print(obj, 3333)
三、hashlib模块(*****)
我们以后存密码时一定要存成密文,不能是明文,那如何把字符串加密成密文呢?python提供了一个模块hashlib,使我们可以对一个字符串进行加密。下面来学习一下,如下示例:
import hashlib
# 为了防止别人用撞库破解,我们可以再加盐处理
SALT = b'2erer3asdfwerxdf34sdfsdfs90'
def md5(pwd):
obj = hashlib.md5(SALT) # 实例化对象
# 写入要加密的字节,在python3中必须是字节,所以要将字符串转成字节
obj.update(pwd.encode('utf-8'))
v = obj.hexdigest() # 获取密文
return v user = input("请输入用户名:")
pwd = input("请输入密码:") # admin
# md5加密是不可逆的,无法解密,所以验证时要进行密文验证
if user == 'oldboy' and md5(pwd) == 'c5395258d82599e5f1bec3be1e4dea4a':
print('登录成功')
else:
print('登录失败')
四、logging日志模块(****)
先思考一个问题:为什么要有日志?日志是给开发人员看,用于排查错误。
1、python为我们提供了一个logging模块,它是一个用于便捷记录日志且线程安全的模块。
函数式的简单配置如下:
import logging
logging.debug('debug message') # level = 10
logging.info('info message') #
logging.warning('warning message') #
logging.error('error message') #
logging.critical('critical message') #
logging.log(60, '自定义的level')
# 结果为:
# WARNING:root:warning message
# ERROR:root:error message
# CRITICAL:root:critical message
# Level 60:root:自定义的level
默认情况python的logging模块将日志打印到了标准输出中,且只显示了大于等于warning级别的日志,这说明默认的日志级别level设置为warning(日志级别等级critical > error > warning > info > debug),默认的日志显示格式为:日志级别:logger名称:用户输出消息。
logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用的参数有:
filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中;
format:指定handler使用的日志显示格式;
datefmt:指定日期时间格式;
level:设置rootlogger(后边会讲解具体概念)的日志级别;
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”;
stream:用指定的stream创建StreamHandler。可以指定输出到 sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略;
具体参数
具体示例如下:
import logging logger = logging.basicConfig(filename='wllog.txt',
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=20) logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
logging.log(60, '自定义的level')
2、获取当前错误的堆栈信息并写入日志,如下示例:
import logging logger = logging.basicConfig(filename='wllog.txt',
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=30) import traceback def func():
try:
a = a +1
except Exception as e: # e其实是一个对象
# 获取当前错误的堆栈信息,有文件和错误所在行
msg = traceback.format_exc()
logging.error(msg)
# 只写入错误信息描述,没有发生错误文件和错误所在行
# logging.error(str(e))
func()
3、多文件日志
对于上述记录日志的功能,只能将日志记录在单文件中,如果想要设置多个日志文件,logging.basicConfig将无法完成,需要自定义文件和日志操作对象,如下示例:
# 创建一个操作日志的对象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('s1', level=logging.ERROR)
logger1.addHandler(file_handler) logger1.error('') # 再创建一个操作日志的对象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('s2', level=logging.ERROR)
logger2.addHandler(file_handler2) logger2.error('')
日志
如上述创建的两个日志对象
当使用logger1写日志时,会将相应的内容写入l1.log文件中;
当使用logger2写日志时,会将相应的内容写入l2.log文件中;
约束、自定义异常、hashlib模块、logging日志模块的更多相关文章
- hashlib加密模块、logging日志模块
hashlib模块 加密:将明文数据通过一系列算法变成密文数据 目的: 就是为了数据的安全 基本使用 基本使用 import hashlib # 1.先确定算法类型(md5普遍使用) md5 = ha ...
- day31 logging 日志模块
# logging 日志模块 ****** # 记录用户行为或者代码执行过程 # print 来回注释比较麻烦的 # logging # 我能够“一键”控制 # 排错的时候需要打印很多细节来帮助我排错 ...
- Python入门之logging日志模块以及多进程日志
本篇文章主要对 python logging 的介绍加深理解.更主要是 讨论在多进程环境下如何使用logging 来输出日志, 如何安全地切分日志文件. 1. logging日志模块介绍 python ...
- 包,logging日志模块,copy深浅拷贝
一 包 package 包就是一个包含了 __init__.py文件的文件夹 包是模块的一种表现形式,包即模块 首次导入包: 先创建一个执行文件的名称空间 1.创建包下面的__init__.py文件的 ...
- logging 日志模块学习
logging 日志模块,用于记录系统在运行过程中的一些关键信息,以便于对系统的运行状况进行跟踪,所以还是灰常重要滴,下面我就来从入门到放弃的系统学习一下日志既可以在屏幕上显示,又可以在文件中体现. ...
- logging日志模块
为什么要做日志: 审计跟踪:但错误发生时,你需要清除知道该如何处理,通过对日志跟踪,你可以获取该错误发生的具体环境,你需要确切知道什么是什么引起该错误,什么对该错误不会造成影响. 跟踪应用的警告和错误 ...
- python 自动化之路 logging日志模块
logging 日志模块 http://python.usyiyi.cn/python_278/library/logging.html 中文官方http://blog.csdn.net/zyz511 ...
- logging日志模块的使用
logging日志模块的使用 logging模块中有5个日志级别: debug 10 info 20 warning 30 error 40 critical 50 通常使用日志模块,是用字典进行配置 ...
- Python 中 logging 日志模块在多进程环境下的使用
因为我的个人网站 restran.net 已经启用,博客园的内容已经不再更新.请访问我的个人网站获取这篇文章的最新内容,Python 中 logging 日志模块在多进程环境下的使用 使用 Pytho ...
随机推荐
- linux 网络性能优化
最近在对程序进行调优,涉及到了网络通信,学习了一下对网络调优的方法,网上的资料很多,针对软件优化方面,大体上主要有两种方式:一是网卡参数,另一个是内核参数. 一. 网卡参数优化 针对网卡参数优化,需要 ...
- spring学习笔记(四)
1.aop编程 a.前置通知 .... <!-- 配置被代理的对象 --> <bean id="test1Service" class="com. ...
- http://www.allegro-skill.com/thread-2506-1-1.html
http://www.allegro-skill.com/thread-2506-1-1.html
- C++语言基础(4)-构造函数和析构函数
一.构造函数 类似于java,C++中也有构造函数的概念,相关用法如下: 1.1 构造函数的定义 #include <iostream> using namespace std; clas ...
- UI-1-UI入门
课程要点: 创建一个iOS工程 AppDelegate类 UIKit框架以及UIWindow 在window上添加第一个试图UIView NSTimer(定时器) 创建一个iOS工程 PS:接下来简单 ...
- AFNet3.0上传图片
很多iOS应用都会遇到需要上传图片的情况,比如修改个人资料时需要上传自己的头像,最近我也遇到了这种情况,首先参考之前写过的AFNetWorking3.0处理请求头和请求内容. 我们在上述博客的基础之上 ...
- linux上安装python3同时保留python2
linux上安装python3同时保留python2?这个就要用到上篇说到的path变量了. 具体介绍及操作 这里我下载python3.6版本来进行介绍 django默认数据库为sqlite3,所以安 ...
- Redis 哈希槽
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余 ...
- 我的第六个java程序 spring-bean
配置文件 Beans.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&quo ...
- c++标准库之容器
C++最原始的容器之一是数组.数组的特点有: 1.大小固定 2.单独存在的数组建立在栈上,作为对象成员存在的数组建立在堆上还是栈上则要看作为宿主对象是被建立在堆上还是栈上.栈空间是有限的,所以如果数组 ...