模块

模块的三种类型:

  1. 内置模块:安装python解释器的时候一起装上的
  2. 第三方模块:扩展模块:需要自己安装
  3. 自定义模块:你写的py文件

序列化模块

序列:

  1. 列表
  2. 元组
  3. 字符串 *
  4. bytes *

什么叫序列化

把一个数据类型转换成字符串,bytes类型的过程就是序列化

为什么要把有个数据类型序列化

  1. 把一个数据类型储存到文件中,持久储存

  2. 把一个数据类型通过网络传输的时候

    当然你会说用eval()函数,将字符串对象转化为有效的表达式参与求值运算返回计算结果,但是这样不安全.

stu = {'name':'何青','sex':'male'}
ret = str(stu)
print([ret])
print([eval(ret)])  # 用户输入的、文件读入的、网络传入的
>>>["{'name': '何青', 'sex': 'male'}"]
[{'name': '何青', 'sex': 'male'}]

json模块

json模块的作用是把数据类型序列化储存

  • json支持所有语言
  • 只支持非常少的数据类型:字典的key必须是字符串,只支持:数字,字符串,列表,字典
import json
lst = [1,2,3,4,'aaa','bbb']
ret = json.dumps(lst)  # 序列化的过程
print(lst,type(lst))
print(ret,type(ret))
d = json.loads(ret)    # 反序列化的过程
print('d-->',d,type(d))

[1, 2, 3, 4, 'aaa', 'bbb'] 
[1, 2, 3, 4, "aaa", "bbb"] 
d--> [1, 2, 3, 4, 'aaa', 'bbb'] 

pickle模块

pickle模块只支持python语言,但是支持几乎所有的数据类型,在编程中我们还是经常使用json模块.

import pickle
class Course():
    def __init__(self,name,price):
        self.name = name
        self.price = price

python = Course('python',29800)
ret = pickle.dumps(python)#序列化
print(ret)
>>>b'\x80\x03c__main__\nCourse\nq\x00)\x81q\x01}q\x02(X\x04\x00\x00\x00nameq\x03X\x06\x00\x00\x00pythonq\x04X\x05\x00\x00\x00priceq\x05Mhtub.'

p = pickle.loads(ret)#反序列化
print(p.name,p.price)
>>python 29800

时间模块

表示时间的三种方式

time模块被称为时间模块,在python中,通常用这三种方法来表示时间:

  1. 时间戳(Timestamp)

    时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.是float类型

    import time
    time.time()#获取当前的时间戳
    

    时间戳是一个经过加密后形成的凭证文档,包括3部分:

    1. 需加时间戳的文件摘要(digest)
    2. DTS收到的文件的日期和时间
    3. DTS的数字签名

    过程:将需要时间戳的文件用Hash编码加密成摘要,发到DTS,DTS加入收到文件摘要的日期和时间信息后再对该文件加密,最后发给用户.

    书面签署文件的时间是由签署本人自己写的,而数字时间戳是由认证单位的DTS添加的,以DTS收到的文件的时间为依据.

  2. 时间元组(struct_time)

    时间元组一共有9个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)

    索引(Index) 属性(Attribute) 值(Values)
    0 tm_year(年) 比如2011
    1 tm_mon(月) 1 - 12
    2 tm_mday(日) 1 - 31
    3 tm_hour(时) 0 - 23
    4 tm_min(分) 0 - 59
    5 tm_sec(秒) 0 - 60
    6 tm_wday(weekday) 0 - 6(0表示周一)
    7 tm_yday(一年中的第几天) 1 - 366
    8 tm_isdst(是否是夏令时) 默认为0
  3. 时间字符串(Format string)

    在python中使用下表格式化符号对时间进行格式化:

    %y 两位数的年份表示(00-99)
    %Y 四位数的年份表示(000-9999)
    %m 月份(01-12)
    %d 月内中的一天(0-31)
    %H 24小时制小时数(0-23)
    %I 12小时制小时数(01-12)
    %M 分钟数(00=59)
    %S 秒(00-61)                     (2)
    %a 本地简化星期名称
    %A 本地完整星期名称
    %b 本地简化的月份名称
    %B 本地完整的月份名称
    %c 本地相应的日期表示和时间表示
    %j 年内的一天(001-366)
    %p 本地A.M.或P.M.的等价符            (1)
    %U 一年中的星期数(00-53)星期天为星期的开始    (3)
    %w 星期(0-6),星期天为星期的开始             (3)
    %W 一年中的星期数(00-53)星期一为星期的开始
    %x 本地相应的日期表示
    %X 本地相应的时间表示
    %Z 当前时区的名称
    %% %号本身
    

    3个数字的含义:

    1. %p只有与%I配合使用才有效果.
    2. 文档中的强调确实是0~61,而不是59秒,闰年占两秒
    3. 当使用striptime()函数时,只有这一年的周数和天数确定时%U和%W才会被计算.

认识几种格式:

#导入时间模块
>>>import time

#时间戳
>>>time.time()
1500875844.800804

#时间字符串
>>>time.strftime("%Y-%m-%d %X")
'2017-07-24 13:54:37'
>>>time.strftime("%Y-%m-%d %H-%M-%S")
'2017-07-24 13-55-04'

#时间元组:localtime将一个时间戳转换为当前时区的struct_time
time.localtime()
time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24,
          tm_hour=13, tm_min=59, tm_sec=37, 
                 tm_wday=0, tm_yday=205, tm_isdst=0)

小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;元组则是用来操作时间的

几种格式的转换

image.png

time模块

在time模块里边还有一些内置函数有做时间处理的,也有做格式转换的:

time函数

time()函数用于返回当前时间的时间戳.

import time
print('当前的时间戳为%f'%time.time())#第一个time是time模块

localtime([secs])函数

localtime()函数的作用是格式化时间戳为本地时间.如果secs参数未输入,就以当前时间为转换标准.secs 为time.struct_time的秒数.

import time 
print(time.localtime())
>>>time.struct_time(tm_year=2018, tm_mon=9, tm_mday=4, tm_hour=16, tm_min=23, tm_sec=45, tm_wday=1, tm_yday=247, tm_isdst=0)

gmtime([secs])函数

gmtime()函数用于将一个时间戳转换为UTC时区的struct_time,可选参数secs表示为从1970年1月1日到现在的秒数.gmtime()函数的默认值为time.time(),函数返回time.struct_time类型的对象(struct_time是在time模块中定义的表示时间的对象)

import time
print(time.gmtime())
>>time.struct_time(tm_year=2018, tm_mon=9, tm_mday=4, tm_hour=8, tm_min=32, tm_sec=39, tm_wday=1, tm_yday=247, tm_isdst=0)

看上边的结果作者是在东八区,与零时区差8个小时,gmtime()函数把时区换成了零时区.

mktime(t)函数

mktime()函数用于执行与gmtime()函数和localtime()函数相反的操作,接受struct_time对象作为参数,返回用秒作为时间表示的浮点数.输入的值不是合法时间,就会触发OverflowError或ValueError.

import time
t = (2018,9,4,16,34,56,1,247,0)
print(time.mktime(t))
>>>1536050096.0

asctime([t])函数

asctime()函数用于接受时间元组并返回一个可读的形式的24个字符的字符串.

import time
t =(2018,9,4,16,34,56,1,247,0)
print(time.asctime(t))
>>>Tue Sep  4 16:34:56 2018

ctime([secs])函数

ctime函数用于把时间戳转换为asctime()函数格式的形式.可以指定参数secs,也可以空着,它默认将time.time()做为参数.ctime的作用相当于asctime(localtime(secs))

import time
print(time.ctime())
>>>Tue Sep  4 16:55:00 2018

sleep函数

sleep函数用于推迟调用线程的运行,可通过输入secs时间来指定推迟时间,

import time
print('start:%s'%time.ctime())
time.sleep(20)
print('End:%s'%time.ctime())
>>>start:Tue Sep  4 17:00:47 2018
End:Tue Sep  4 17:01:07 2018

由结果可以知道,输出时间间隔了20秒

clock()函数

clock函数,是用来判断CPU的运行时间的并以浮点数返回,衡量不同程序的运行时间.在Windows系统上第一层返回的是程序的运行时间,第二次调用返回的是第一次调用后到第二次调用的时间间隔.

import time
def procedure():
    time.sleep(5)
t1 = time.clock()
procedure()
print(time.clock-t1)

strftime()函数

strftime函数用于接受时间元组,并返回可读字符串表示的当地时间.

import time
print(time.strftime('%Y-%m-%d',time.localtime()))
>>>2018-09-04

strptime()函数

strptime()函数用于根据指定格式把一个时间字符串解析为一个时间元组.

import time
print(time.strptime('4 Sep 17','%d%b%y'))
>>>time.struct_time(tm_year=2017, tm_mon=9, tm_mday=4, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=247, tm_isdst=-1)

随机函数模块

取随机小数:

random()可以去随机小数,默认大于0且小于1的数,

import random
random.random()

也可以指定区间

import random
random,uniform(2,4)#大于2小于4的小数

取随机整数:

>>> random.randint(1,5)  # 大于等于1且小于等于5之间的整数
>>> random.randrange(1,10,2) # 大于等于1且小于10之间的奇数

随机选择返回:

#随机选择一个返回
>>> random.choice([1,'23',[4,5]])  # #1或者23或者[4,5]
#随机选择多个返回,返回的个数为函数的第二个参数
>>> random.sample([1,'23',[4,5]],2) # #列表元素任意2个组合
[[4, 5], '23']

打乱列表顺序

>>> item=[1,3,5,7,9]
>>> random.shuffle(item) # 打乱次序
>>> item
[5, 1, 3, 7, 9]
>>> random.shuffle(item)
>>> item
[5, 9, 7, 1, 3]

随机生成验证码

#请你生成一个6位数的验证码
#字母怎么生成 chr()把数字转变成字母
st = random.randint(65,90)
print(chr(st))
num = random.randint(97,122)
print(chr(num))
#每一位上出现的内容可以是数字,也可以是字母
def get_code(n=6,alph_flag=True):
    code=''
    for i in range(n):
        c = str(random.randint(0,9))
        if alph_flag:
            alpha_upper=chr(random.randint(65, 90))
            alpha_lower=chr(random.randint(97, 122))
            c = random.choice([c,alpha_upper,alpha_lower])
        code +=c
    return code
ret = get_code(6)
print(ret)

OS模块

# os 和操作系统交互
    # 文件和文件夹的操作
        # os.remove
        # os.rename
        # os.mkdir
        # os.makedirs
        # os.rmdir
        # os.removedirs
        # os.listdir
        # os.stat 获取文件的信息
    # 路径的操作
        # os.path.join   目录的拼接
        # os.path.split(path) # 将路径分割成两个部分,目录、文件/文件夹的名字
        # os.path.dirname(path) # 返回这个path的上一级目录
        # os.path.basename(path) # 文件/文件夹的名字
        # os.path.exits  这个路径是否存在
        # os.path.isfile 是否文件目录
        # os.path.isdir  是否文件夹目录
        # os.path.abspath 规范文件目录、返回一个绝对路径
        # os.path.getsize
    # 和python程序的工作目录相关的
        # getcwd  # 获取当前的工作目录 get current working dir
        # chdir   # 改变当前的工作目录 change dir
    # 执行操作系统命令
        # os.system(命令)
        # os.popen(命令).read()
# __file__文件中的一个内置变量,描述的是这个文件的绝对路径
os路径处理
#方式一:推荐使用
import os
#具体应用
import os,sys
possible_topdir = os.path.normpath(os.path.join(
    os.path.abspath(__file__),
    os.pardir, #上一级
    os.pardir,
    os.pardir
))
sys.path.insert(0,possible_topdir)


#方式二:不推荐使用
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

sys模块

# sys 和python解释器
    # sys.argv 执行py文件的时候传入的参数
    # sys.path 查看模块搜索路径 import 模块的时候从这个路径下来寻找
    # sys.modules 查看当前导入的模块和它的命名空间

collections模块

根据基础数据类型又做了一些扩展,例如:counter,deque,defaultdict,

namedtuple,orderedDict.

1.namedtuple: 生成可以使用名字来访问元素内容的tuple

2.deque: 双端队列,可以快速的从另外一侧追加和推出对像

3.Counter: 计数器,主要用来计数

4.OrderedDict: 有序字典

5.defaultdict: 带有默认值的字典

namedtuple

生成可以使用名字来访问元素内容的tuple,

例如:

p =(1,2)

单看这个元组,很难用来表示一个坐标,但是用了namedtiple定义就不一样了.

from collections import namedtuple:
Point = namedtuple('Point',['x','y'])
p = Point(1,2)
pringt(p.x)
print(p.y)
>>>1
>>>2
from collections import namedtuple
birth = namedtuple('Struct_time',['year','month','day'])
b1 = birth(2018,9,5)
print(type(b1))
print(b1.year)
print(b1.month)
print(b1.day)
print(b1)
# ['year','month','day']是对象属性名
# Struct_time是类 的名字
# 这个类最大的特点就是一旦实例化 不能修改属性的值

deque(双端队列)

在使用list储存数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线储存,数据量大的时候,插入和删除效率很低.

deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

>>> from collections import deque
>>> q = deque(['a', 'b', 'c'])
>>> q.append('x')
>>> q.appendleft('y')
>>> q
deque(['y', 'a', 'b', 'c', 'x'])

deque除了实现list的append()pop()外,还支持appendleft()popleft(),这样就可以非常高效地往头部添加或删除元素。

OrderedDict

使用dict时,key是无序的,在对dict做迭代的时候,我们无法确定key的顺序.

如果要保持Key的顺序,可以用OrderedDict:

>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d # dict的Key是无序的
{'a': 1, 'c': 3, 'b': 2}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od = OrderedDict()
>>> od['z'] = 1
>>> od['y'] = 2
>>> od['x'] = 3
>>> od.keys() # 按照插入的Key的顺序返回
['z', 'y', 'x']

注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:

defaultdict

有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于 66` `的值保存至字典的第一个key中,将小于66的值保存至第二个key的值中。

即: {'k1': 大于66` `,'k2': 小于66``}

values = [11, 22, 33,44,55,66,77,88,99,90]

my_dict = {}

for value in  values:
    if value>66:
        if my_dict.has_key('k1'):
            my_dict['k1'].append(value)
        else:
            my_dict['k1'] = [value]
    else:
        if my_dict.has_key('k2'):
            my_dict['k2'].append(value)
        else:
            my_dict['k2'] = [value]

原生字典解决方法
from collections import defaultdict

values = [11, 22, 33,44,55,66,77,88,99,90]

my_dict = defaultdict(list)

for value in  values:
    if value>66:
        my_dict['k1'].append(value)
    else:
        my_dict['k2'].append(value)

defaultdict字典解决方法

Counter

Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。

c = Counter('abcdeabcdabcaba')
print c
输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})

hanslib * * ***

hanslib是一种内部不只有一种算法的模块.但是由于数据不安全性,为了保证用户信息的绝对安全,所以所有人的密码都不能以明文的形式储存,而应该经过适当的处理以密文的形式存起来.

hanslib被称为摘要算法,它通过一个函数把任意长度的摘要digest,目的是为了发现原始数据是否被人篡改过.(用16进制的字节表达)

hanslib函数是一个单向函数,计算容易,反推难,常见的方法有MD5(32位)SHA(40)位.

import hashlib
 
md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?')
print md5.hexdigest()

计算结果如下:
d26a53750bc40b38b65a520292f69306
md5_obj = hashlib.md5()
md5_obj.update(b'alex3714')
md5_obj.update('999'.encode('utf-8'))
ret = md5_obj.hexdigest()
print(ret,type(ret),len(ret))
#数据量大的话可以分开update()然后再统一输出.

登录验证:

import hashlib
usrname = input('username : ')
passwd = input('password : ')
with open('userinfo') as f:
    for line in f:
        usr,pwd = line.strip().split('|')
        if usrname == usr and get_md5(passwd) == pwd:
            print('登录成功')
            break
    else:
        print('登录失败')

多种算法
md5算法 :32位16进制的数字字符组成的字符串
应用最广大的摘要算法
效率高,相对不复杂,如果只是传统摘要不安全

sha算法 :40位的16进制的数字字符组成的字符串
sha算法要比md5算法更复杂
且shan n的数字越大算法越复杂,耗时越久,结果越长,越安全

加盐,动态加盐

为了保证摘要算法的安全性,我们可以采用加盐的范式来对数据进行隐藏.

加盐
def get_md5(s):
    md5_obj = hashlib.md5('盐'.encode('utf-8'))
    md5_obj.update(s.encode('utf-8'))
    ret = md5_obj.hexdigest()
    return ret

但是这种方法也不好,如果被人知道了盐是什么的话依然你能破解出密码.所以我们采用动态加盐的方式.

动态加盐
每一个用户创建一个盐 - 用户名
def get_md5(user,s):
    md5_obj = hashlib.md5(user.encode('utf-8'))
    md5_obj.update(s.encode('utf-8'))
    ret = md5_obj.hexdigest()
    return ret

文件 的一致性

我们在下载文件的时候如何判断下载的文件就是原文件,那么,我们可以采用摘要函数来对其进行判断.

# 下载的是视频、或者大文件
# 应该是以rb的形式来读 读出来的都是bytes
# 并且不能按行读 也不能一次性读出来
# getsize()  -->  字节大小
# 10240
# 1024
# D:\讲师课程文件\python讲师 Jingliyang\day24\video\3.习题讲解2.mp4
import os
import hashlib
def get_file_md5(file_path,buffer = 1024):
    md5_obj = hashlib.md5()
    # file_path = r'3.习题讲解2.mp4'   # 路径里不能有空格
    file_size = os.path.getsize(file_path)
    with open(file_path,'rb') as f:
        while file_size:
            content = f.read(buffer)   # 1024 1024 1024  。。。 5
            file_size -= len(content) #  5 -=5
            md5_obj.update(content)
    return md5_obj.hexdigest()

configparser *

该模块适用于配置文件,当你需要把你的userinfo文件copy到其他目录或者电脑下,不在当前这个userinfo文件所在的目录去执行py文件的时候,需要把路径记录在这里

import configparser

config = configparser.ConfigParser()

config["DEFAULT"] = {'ServerAliveInterval': '45',
                      'Compression': 'yes',
                     'CompressionLevel': '9',
                     'ForwardX11':'yes'
                     }

config['bitbucket.org'] = {'User':'hg'}

config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}

with open('example.ini', 'w') as configfile:
   config.write(configfile)
config = configparser.ConfigParser()
print(config.sections())        #  []
config.read('example.ini')
print(config.sections())        #   ['bitbucket.org', 'topsecret.server.com']

print('bytebong.com' in config) # False
print('bitbucket.org' in config) # True
print(config['bitbucket.org']["user"])  # hg
print(config['DEFAULT']['Compression']) #yes
print(config['topsecret.server.com']['ForwardX11'])  #no
print(config['bitbucket.org'])          #
for key in config['bitbucket.org']:     # 注意,有default会默认default的键
    print(key)
print(config.options('bitbucket.org'))  # 同for循环,找到'bitbucket.org'下所有键
print(config.items('bitbucket.org'))    #找到'bitbucket.org'下所有键值对
print(config.get('bitbucket.org','compression')) # yes       get方法Section下的key对应的value

logging** * **

默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),默认的日志格式为日志级别:Logger名称:用户输出消息。

import logging  
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message') 
import logging  
logging.basicConfig(level=logging.DEBUG,  
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
                    datefmt='%a, %d %b %Y %H:%M:%S',  
                    filename='/tmp/test.log',  
                    filemode='w')  
  
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message')
# 对象的配置
    # 解决中文问题
    # 同时向文件和屏幕输出内容

# 先创建一个log对象 logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# 还要创建一个控制文件输出的文件操作符
fh = logging.FileHandler('mylog.log')
# 还要创建一个控制屏幕输出的屏幕操作符
sh = logging.StreamHandler()
# 要创建一个格式
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fmt2 = logging.Formatter('%(asctime)s - %(name)s[line:%(lineno)d] - %(levelname)s - %(message)s')

# 文件操作符 绑定一个 格式
fh.setFormatter(fmt)
# 屏幕操作符 绑定一个 格式
sh.setFormatter(fmt2)
sh.setLevel(logging.WARNING)
# logger对象来绑定:文件操作符, 屏幕操作符
logger.addHandler(sh)
logger.addHandler(fh)


logger.debug('debug message')    # 计算或者工作的细节
logger.info('info message')      # 记录一些用户的增删改查的操作
logger.warning('input a string type') # 警告操作
logger.error('error message')     # 错误操作
logger.critical('critical message')  # 批判的 直接导致程序出错退出的

你可能感兴趣的:(模块)