1、MD5加密模块
MD5是一种不可逆的加密算法, 是安全而且可靠的.
在某些网站上能够搜到MD5解密工具, 其实并没有解密工具, 而是"撞库"的方式. 网站将一些MD5数据保存起来了, 在解密时通过排列组合将匹配到的信息反馈给用户.
对于这种情况, 只需要在用MD5时给加个bytes参数就OK.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import hashlib 2 def jiami(content): 3 EXTRA = b"abcdefg12345higklmn678910opqrst" 4 obj = hashlib.md5(EXTRA) # 额外加密 5 obj.update(content.encode("utf8")) # 给obj添加明文, 明文必须是bytes类型 6 return obj.hexdigest() # 输出obj中的密文 7 8 print(jiami("大头大头下雨不愁")) # 2bda31af1f147daf99d318c240a68824
2、logging日志模块
通过logging来记录日志.
用的时候直接调用就OK, 不需要去记.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import logging 2 file_handler = logging.FileHandler("choice_movie_age","a",encoding="utf8") 3 file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")) 4 logger = logging.Logger("脚本程序名字",level=20) # 记录级别大于等于20 的日志等级 5 logger.addHandler(file_handler) 6 logger.info("info信息....")
项目中使用logging
from logging.handlers import RotatingFileHandler
def set_log(): # 设置日志的记录等级 logging.basicConfig(level="DEBUG") # 调试debug级 # 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限 file_log_handler = RotatingFileHandler("logs/log", encoding="utf8", maxBytes=1024 * 1024 * 300, backupCount=10) # 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息 formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s') # 为刚创建的日志记录器设置日志记录格式 file_log_handler.setFormatter(formatter) # 为全局的日志工具对象(flaskapp使用的)添加日志记录器 logging.getLogger().addHandler(file_log_handler)
注意:
RotatingFileHandler, 类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。
项目练习: 小脚本 + 日志记录: 观看血腥恐怖动作电影, 年龄大于60岁不让观看, 年龄小于15岁不让观看, 性别女的不让观看.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # 配置日志操作 2 import traceback 3 import logging 4 file_handler = logging.FileHandler("choice_movie_age","a",encoding="utf8") 5 file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")) 6 logger = logging.Logger("脚本程序名字",level=20) # 记录级别大于等于20 的日志等级 7 logger.addHandler(file_handler) 8 9 10 # 自定义异常 11 class BigAgeException(Exception): 12 pass 13 class SmallAgeException(Exception): 14 pass 15 class GenderException(Exception): 16 pass 17 18 class WatchMovie: 19 def __init__(self,name,age,gender): 20 self.name = name 21 self.age = age 22 self.gender = gender 23 def judge(self): 24 if self.age < 15: 25 raise SmallAgeException("年龄太小不适合观看") 26 elif self.age > 60: 27 raise BigAgeException("年龄太大不宜观看") 28 elif self.gender == "女": 29 raise GenderException("泰国暴力女性不宜观看") 30 else: 31 logger.info("%s观看了电影" %(self.name)) # 日志记录....观看了电影 32 print("观影愉快") 33 34 while 1: 35 try: 36 name = input("您的姓名:") 37 age = int(input("您的年龄: ")) 38 gender = input("您的性别: ") 39 obj = WatchMovie(name,age,gender) 40 print(obj.judge()) 41 except SmallAgeException as s: 42 msg = traceback.format_exc() 43 logger.warning(msg) 44 except BigAgeException as b: 45 msg = traceback.format_exc() 46 logger.warning(msg) 47 except GenderException as b: 48 msg = traceback.format_exc() 49 logger.warning(msg) 50 except Exception as e: 51 msg = traceback.format_exc() 52 logger.error(msg)
3、collection模块
collection模块主要封装了一些关于集合类的操作.
3.1 Counter 计数器, 用来计数, 结果是一个类似于字典的Counter对象.
1 from collections import Counter 2 s = "wo you yi ge meng xiang jiu shi you yi tian quan shi jie dou mei you zhong zu qi shi" 3 print(Counter(s)) # 结果像字典一样可以调用
3.2 栈(先进后出)
python没有stack模块, 粗略手写一个实现栈的类(此版本有很严重的高并发问题)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class StackFullError(Exception): 2 pass 3 class StackEmptyError(Exception): 4 pass 5 class Stack: 6 def __init__(self,size): 7 self.size = size 8 self.index = 0 9 self.lst = [] 10 def push(self,item): 11 if self.index == self.size: 12 raise StackFullError("栈满") 13 self.lst.insert(self.index,item) 14 # self.lst[self.index] = item 15 self.index += 1 16 def pop(self): 17 if self.index == 0: 18 raise StackEmptyError("栈空") 19 self.index -= 1 20 item = self.lst.pop(self.index) 21 return item 22 23 s = Stack(5) 24 s.push("馒头1") 25 s.push("馒头2") 26 s.push("馒头3") 27 s.push("馒头4") 28 s.push("馒头5") 29 print(s.pop()) 30 print(s.pop()) 31 print(s.pop()) 32 print(s.pop()) 33 print(s.pop())
3.3 队列(先进先出)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import queue 2 q = queue.Queue(4) # q 里放四个元素 3 q.put("馒头1") 4 q.put("馒头2") 5 q.put("馒头3") 6 q.put("馒头4") 7 # q.put("馒头5",0) # 第二个参数为0, 能看到阻塞信息. queue.Full 8 print(q.get()) 9 print(q.get()) 10 print(q.get()) 11 print(q.get())
3.4 双向队列(左右可进可出)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from collections import deque 2 dq = deque() 3 dq.append("1号") 4 dq.append("2号") 5 dq.appendleft("3号") 6 dq.appendleft("4号") 7 print(dq.pop()) 8 print(dq.pop()) 9 print(dq.popleft()) 10 print(dq.popleft()) 11 print(dq.popleft()) # 队列里为空时会报错不会阻塞
3.5 namedtuple 命名元组
给元组内的元素进行命名. 比如. 我们说(x, y) 这是一个元组. 同时. 我们还可以认为这是一个点坐标. 这时, 我们就可以使用namedtuple对元素进行命名.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from collections import namedtuple 2 point = namedtuple("三维坐标",["x","y","z"]) 3 p = point(20,56,89) 4 print(p.x) 5 print(p.y) 6 print(p.z) 7 # p.z = 58 # 不能修改, 命名元组也是一个元组,不可变
3.6 defaultdict 默认值字典可以给字典设置默认值. 当key不存在时. 直接获取默认值.
from collections import defaultdict
dic = defaultdict(list) -----> 设置默认值是一个list, 是一个空列表
print(dic["大手笔"]) dic[ ''大手笔'' ] = []
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from collections import defaultdict 2 lst = [11,22,33,44,55,66,77,88,99,100] 3 dic = defaultdict(list) # 参数必须是可调用的, 即 参数()... 如果dic中某个键没有对应值时创建一个空[], 也可以自己 4 # 写个函数,放函数名, dic对象中键名没有对应值的话默认会执行函数并返回函数值 5 6 for i in lst: 7 if i > 55: 8 dic["大于55"].append(i) # 从dic里面找"大于55",有的话直接append(), 没有的话会默认生成一个list 9 # dic.setdefault("大于55").append(i) 10 else: 11 dic["小于等于55"].append(i) 12 # dic.setdefault("xiao于55").append(i) 13 print(dic)
4、time模块
在python中时间分成三种表现形式:
1. 时间戳(timestamp). 时间戳使用的是从1970年年01月01日 00点00分00秒到现在 一共经过了多少秒... 使用float来表示 .
2. 格式化时间(strftime). 这个时间可以根据我们的需要对时间进行任意的格式化.
3. 结构化时间(struct_time). 这个时间主要可以把时间进行分类划分. 比如. 1970 年年01月01日 00点00分00秒, 这个时间可以被细分为年, 月, 日.....一大堆东西.
1 %y 两位数的年年份表示(00-99) 2 %Y 四位数的年年份表示(000-9999) 3 %m 月份(01-12) 4 %d 月内中的⼀一天(0-31) 5 %H 24小时制小时数(0-23) 6 %I 12小时制小时数(01-12) 7 %M 分钟数(00=59) 8 %S 秒(00-59) 9 %a 本地简化星期名称 10 %A 本地完整星期名称 11 %b 本地简化的月份名称 12 %B 本地完整的月份名称 13 %c 本地相应的日期表示和时间表示 14 %j 年年内的一天(001-366) 15 %p 本地A.M.或P.M.的等价符 16 %U 一年年中的星期数(00-53)星期天为星期的开始 17 %w 星期(0-6),星期天为星期的开始 18 %W 一年年中的星期数(00-53)星期一为星期的开始 19 %x 本地相应的日期表示 20 %X 本地相应的时间表示 21 %Z 当前时区的名称 22 %% %号本身
1 # 时间戳 ----> 格式化时间 2 stamp_time = time.time() # 时间戳 3 struck_time = time.gmtime() # 时间戳 -----> 结构化时间(也可以用localtime) 4 f_time = time.strftime("%Y-%m-%d %H:%M:%S",struck_time) # 结构化时间 ----> 格式化时间 5 print(f_time) 6 7 8 # 格式化时间 -----> 时间戳 9 f_time = "2018-11-14 12:53:33" 10 struck_time = time.strptime(f_time,"%Y-%m-%d %H:%M:%S") # 格式化时间 ----> 结构化时间 11 stamp_time2 = time.mktime(struck_time) # 结构化时间 -----> 时间戳 12 print(stamp_time2)
(时间戳 <----------> 格式化时间) 的相互转换?
计算时间差的两种方案:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # 计算时间差的两种方案 2 start_time = "2018-11-21 12:15:20" 3 end_time = "2018-11-21 15:28:59" 4 def trans(t): 5 struck_time = time.strptime(t,"%Y-%m-%d %H:%M:%S") 6 stamp_time = time.mktime(struck_time) 7 return stamp_time 8 9 dis_time = abs(trans(end_time) - trans(start_time)) 10 11 # 第一种方案 12 m,s = divmod(dis_time,60) 13 h,m = divmod(m,60) 14 d,h = divmod(h,24) 15 print(f"从开始到结束的时间差为{int(d)}天{int(h)}时{int(m)}分{int(s)}秒") 16 17 18 # 第二种方案 19 struck_time = time.gmtime(dis_time) 20 print(f"从开始到结束的时间差为{struck_time.tm_year - 1970}年" 21 f"{struck_time.tm_mon - 1}月" 22 f"{struck_time.tm_mday-1}天" 23 f"{struck_time.tm_hour}时" 24 f"{struck_time.tm_min}分" 25 f"{struck_time.tm_sec}秒")
5、random模块 ----> 所有随机的操作
1 import random 2 3 print(random.random()) # (0,1)之间小数 4 print(random.uniform(1,10)) # (0,10)之间小数 5 print(random.randint(1,10)) # [1,10]之间的整数,包括1,10 6 print(random.randrange(1,10,3)) # 1到10,每三个取一个的随机数 7 print(random.choice([1,25,"山东",[25,"丰富"],None])) # []中的任意一个 8 print(random.sample([11,456,"马东北",[25,"单位"],{"鲁":"山东"}],3)) # []中的任意三个 9 lst = [1,2,3,4,5,6,7] 10 random.shuffle(lst) # 将lst随意打散
6、os模块 ----> 和操作系统相关的操作
1 import os # 操作操作系统的 2 os.makedirs("mulu1/mulu11") # 在当前程序所在的文件夹中创建"目录1",在"目录1"里创建"目录11",可以循环一直添加. 3 os.removedirs("mulu1/mulu11") # 若目录为空则直接删除,并递归到上层目录, 如若也为空,继续删, 不为空的话则会报错. 4 os.mkdir('dirname') # 创建单级目录 5 os.rmdir('dirname') # 删除单级目录, 不为空则删除不了 6 print(os.listdir("../")) # 以列表的方式返回指定路径中的文件及文件夹,和隐藏文件 7 os.remove("mulu") # 移除文件 8 os.rename("../day003+","../day003 +") # 给指定文件夹重新命名 "../"表示上一级目录 9 10 # -------------------------------------------------------------------------------------------------------------- 11 print(os.stat("text1")) # 获取文件或目录的所有信息 12 os.stat_result(st_mode=16895, st_ino=24488322973829161, st_dev=440696584, st_nlink=1, st_uid=0, 13 st_gid=0, st_size=0, st_atime=1542194130, st_mtime=1542194130, st_ctime=1542193782) 14 os.stat(path) #属性解读: 15 st_mode #inode 保护模式 16 st_ino #inode 节点号 17 st_dev #inode 驻留留的设备 18 st_nlink #inode 的链接数 19 st_uid #所有者的用户ID 20 st_gid #所有者的组ID 21 st_size #普通⽂文件以字节为单位的⼤大⼩小;包含等待某些特殊⽂文件的数据 22 st_atime #上次访问的时间 23 st_mtime #最后⼀一次修改的时间 24 st_ctime #由操作系统报告的"ctime".在某些系统上(如Unix)是最新的元数据更更改的时间,在其它系统上(如Windows)是创建时间(详细信息参⻅见平台的⽂文档)。 25 # ---------------------------------------------------------------------------------------------------------------------- 26 27 print(os.system("dir")) # 直接执行命令行程序, 会乱码 28 print(os.popen("dir").read()) # 直接执行命令行程序, 但不会乱码 29 print(os.getcwd()) # 获取当前程序所在的文件夹目录 30 31 # os.path系列 32 os.path.abspath("text1") # 获取绝对路径, 包括上级, 上上级..... 33 os.path.split("E:日常练习day021\text1") # 将path分割成文件目录和文件名,并以元组的形式返回('E:\日常练习\day021', 'text1') 34 os.path.dirname("E:日常练习day021\text1") # 返回除path最后文件的之前所有路径 E:日常练习day021 35 os.path.basename("E:日常练习day021\text1") # 返回path最后的文件名 text1 36 # 其实 os.path.dirname()就是os.path.split()的第一个元素, os.path.basename()就是第二个元素. 37 38 os.path.exists("text1") # 如果"text1"存在,返回True;如果"text1"不不存在,返回False(只能找到当前路径) 39 os.path.isabs("text1") # 如果"text1"是绝对路路径,返回True 40 os.path.isfile("text1") # 如果"text1"是一个存在的文件,返回True。否则返回False 41 os.path.isdir("text1") # 如果"text1"是一个存在的目录,则返回True。否则返回False 42 43 path = "E:日常练习day021\text1" 44 os.path.join(path,"望月") # 路径拼接, 即 "E:日常练习day021\text1望月" 45 46 path = "E:日常练习业day021\text1望月" 47 print(os.path.getsize(path)) # 返回path的大小
7、sys模块 ----> 和解释器相关的操作
1 import sys # ----> 操作解释器的
2 sys.argv # 命令⾏行行参数List,第⼀一个元素是程序本身路路径
3 sys.exit() # 退出程序,正常退出时exit(0),错误退出sys.exit(1)
4 print(sys.version) #获取Python解释程序的版本信息
5 pr/int(sys.platform) #返回操作系统平台名称
6 print(sys.path) # 返回模块的搜索路径
7 sys.path.append("e:/") # 当路径移动时, 可直接将新的路径添加进去, 就能查找到.
8 sys.modules[__name__] # 获取到当前文件的所有内容 -----> 一般用于反射,如 clss = getattr(sys.modules[__name__],role)