python摸爬滚打之day21---- 模块

1、MD5加密模块

  MD5是一种不可逆的加密算法, 是安全而且可靠的.

   在某些网站上能够搜到MD5解密工具, 其实并没有解密工具, 而是"撞库"的方式. 网站将一些MD5数据保存起来了, 在解密时通过排列组合将匹配到的信息反馈给用户. 

  对于这种情况, 只需要在用MD5时给加个bytes参数就OK.

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
MD5加密

2、logging日志模块

  通过logging来记录日志.

  用的时候直接调用就OK, 不需要去记.

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日志记录
项目中使用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岁不让观看, 性别女的不让观看.
 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)
logging脚本练习

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模块, 粗略手写一个实现栈的类(此版本有很严重的高并发问题)

 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  队列(先进先出)

 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())
queue队列

  3.4  双向队列(左右可进可出)

 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对元素进行命名.

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       # 不能修改, 命名元组也是一个元组,不可变
namedtuple

  3.6  defaultdict 默认值字典可以给字典设置默认值. 当key不存在时. 直接获取默认值.

    from collections import defaultdict
   dic = defaultdict(list) -----> 设置默认值是一个list, 是一个空列表
   print(dic["大手笔"])  dic[ ''大手笔'' ] = []
 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)
defaultdict

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-36615 %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)

  (时间戳  <---------->  格式化时间) 的相互转换?  

    计算时间差的两种方案: 

 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}秒")
time计算时间差

 

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)

 

posted @ 2018-11-09 17:44  恐水的鱼  Views(176)  Comments(0Edit  收藏  举报