Python(七)—— 内置模块

发布时间:2023年12月28日

16. 内置模块一

16.1 序列化模块

1、定义:

序列化的本质就是将一种数据结构(如字典、列表)等转换成一个特殊的序列(字符串或者bytes)的过程就叫做序列化

2、作用:

序列化除了可以解决写入文件的问题,还可以解决网络传输的问题,比如你将一个list数据结构通过网络传给另个开发者,那么你要想传输出去必须用bytes类型。但是bytes类型只能与字符串类型互相转化,它不能与其他数据结构直接转化,所以,你只能将list → 字符串 → bytes 然后发送,对方收到之后,在decode() 解码成原字符串

16.1.1 json模块(通用)

1、json模块是将满足条件的数据结构转化成特殊的字符串,并且也可以反序列化还原回去

2、json序列化只支持部分Python数据结构:dict,list,tuple,str,int,float,True,False,None

3、用于网络传输:dumps、loads

  • dumps:序列化
import json
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic)     # 序列化:将一个字典转换成一个字符串
print(type(str_dic))          # <class 'str'>
print(str_dic)

# 输出结果:
<class 'str'>
{"k1": "v1", "k2": "v2", "k3": "v3"}

# 注意,json转换完的字符串类型后,字典中的字符串是由""表示的
  • loads:反序列化
import json
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic)     # 序列化
dic2 = json.loads(str_dic)    # 反序列化:将一个字符串格式的字典转换成一个字典
print(type(dic2))             # <class 'dict'>
print(dic2)

# 输出结果:
<class 'dict'>
{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}

# 注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
  • 对于嵌套数据,也可以使用序列化与反序列化
import json
list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]
str_dic = json.dumps(list_dic)     # 序列化
print(type(str_dic))               # <class 'str'>
print(str_dic)

# 输出结果:
<class 'str'>
[1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
import json
list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]
str_dic = json.dumps(list_dic)     # 序列化
list_dic2 = json.loads(str_dic)    # 反序列化
print(type(list_dic2))             # <class 'list'>
print(list_dic2)

# 输出结果:
<class 'list'>
[1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]

4、用于文件写读:dump、load

5、其他参数说明

  • ensure_ascii:当它为True的时候,所有非ASCII码字符显示为\uXXXX序列,只需在dump时设置为ensure_ascii = False 即可,此时存入json的中文即可正常显示

  • separators:分隔符,实际上是(item_separator,dict_separator)的一个元组,默认的就是逗号或者冒号;这表示dictionary内keys之间用, 隔开,而key和value之间用冒号(:)隔开

  • sort_keys:将数据根据keys的值进行排序

6、json序列化存储多个数据到同一个文件中

对于json序列化,存储多个数据到一个文件中是有问题的,默认一个json文件只能存储一个json数据,但是也可以解决,举例说明:

解决方案:每次转化后写入,都加上换行

16.1.2 pickle模块(仅Python用)

1、pickle模块是将Python所有的数据结构以及对象等转化成bytes类型,然后还可以反序列化还原回去

2、只能是Python语言遵循的一种数据转化格式,只能在Python语言中使用,支持Python所有的数据类型包括实例化对象

3、dumps、loads有两个作用

  • 用于网络传输
import pickle
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = pickle.dumps(dic)

dic2 = pickle.loads(str_dic)
print(type(str_dic))      # bytes类型
print(dic2)               # 字典

# 输出结果:
<class 'bytes'>
{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
  • 还可以序列化对象
import pickle

def func():
    print(666)

ret = pickle.dumps(func)
print(ret)
print(type(ret))        # <class 'bytes'>

f1 = pickle.loads(ret)  # f1得到 func函数的内存地址
f1()                    # 执行func函数,打印666

4、dump、load:用于文件写读

import pickle

dic = {(1,2):'yuluo', 1:True, 'set':{1,2,3}}
f = open('pickle序列化',mode='wb')
pickle.dump(dic,f)
f.close()

with open('pickle序列化',mode='wb') as f1:
    pickle.dump(dic,f1)

5、pickle序列化存储多个数据到一个文件中

16.1.3 shelve模块

类似于字典的操作方式去操作特殊的字符串

16.2 os模块

os模块是与操作系统交互的一个接口,它提供的功能多与工作目录,路径,文件等相关

目录指的是:本文件所在的文件夹(当前目录 / 工作目录 / 父级目录)

16.2.1 当前工作目录相关的路径

# 1、获取当前工作目录,即当前python脚本工作的目录路径
os.getcwd()


# 2、改变当前脚本工作目录;相当于shell下cd
os.chdir("dirname")


# 3、返回当前目录: ('.')
os.curdir


# 4、获取当前目录的父目录字符串名:('..')
os.pardir

16.2.2 和文件夹相关

# 1、可生成多层递归目录(重要)
os.makedirs('dirname1/dirname2')


# 2、若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.removedirs('dirname1')


# 3、生成单级目录;相当于shell中mkdir dirname
os.mkdir('dirname')


# 4、删除单级空目录,若目录不为空则无法删除,报错;
# 相当于shell中rmdir dirname os.listdir('dirname')
os.rmdir('dirname')


# 5、列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.listdir('dirname')

16.2.3 和文件相关

# 1、删除一个文件
os.remove()


# 2、重命名文件/目录
os.rename("oldname","newname")


# 3、获取文件/目录信息
os.stat('path/filename')

注意:os.stat('path/filename') 获取文件/目录信息 的结构说明

os.stat('path/filename') 获取文件/目录信息”的结构说明
st_modeinode 保护模式
st_inoinode 节点号
st_devinode 驻留的设备
st_nlinkinode 的链接数
st_uid所有者的用户ID
st_gid所有者的组ID
st_size普通文件以字节为单位的大小;包含等待某些特殊文件的数据
st_atime上次访问的时间
st_mtime最后一次修改的时间
st_ctime元数据最后一次被访问的时间,或者创建时间

16.2.4 和操作系统差异相关

# 1、输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.sep


# 2、输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.linesep


# 3、输出用于分割文件路径的字符串 win下为";",Linux下为":"
os.pathsep


# 4、输出字符串指示当前使用平台 win→'nt'; Linux→'posix'
os.name

16.2.5 和执行系统命令相关

# 1、运行shell命令,直接显示
os.system("bash command")


# 2、运行shell命令,获取执行结果
os.popen("bash command).read()


# 3、获取系统环境变量
os.environ

16.2.6 path系列(路径相关)

# 1、返回path规范化的绝对路径
os.path.abspath(path)


# 2、将path分割成目录和文件名按元组返回
os.path.split(path)


# 3、返回path的目录,其实就是os.path.split(path)的第一个元素
os.path.dirname(path)


# 3、返回path最后的文件名,如何path以/或\结尾,那么就会返回空值,
# 即os.path.split(path)的第二个元素
os.path.basename(path)


# 4、如果path存在,返回True;如果path不存在,返回False
os.path.exists(path)


# 5、如果path是绝对路径,返回True
os.path.isabs(path)


# 6、如果path是一个存在的文件,返回True。否则返回False
os.path.isfile(path)


# 7、如果path是一个存在的目录,则返回True。否则返回False
os.path.isdir(path)


# 8、将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.join(path1[, path2[, ...]])


# 9、返回path所指向的文件或者目录的最后访问时间
os.path.getatime(path)


# 10、返回path所指向的文件或者目录的最后修改时间
os.path.getmtime(path)


# 11、返回path的大小
os.path.getsize(path)

16.3 sys模块

sys模块是与python解释器交互的一个接口

sys.argv        # 命令行参数List,第一个元素是程序本身路径
sys.exit(n)     # 退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version     # 获取Python解释程序的版本信息
sys.path        # 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform    # 返回操作系统平台名称

16.4 hashlib模块

此模块有人称为摘要算法,也叫做加密算法,或者是哈希算法,散列算法等。就是做加密和校验使用,工作原理:它通过一个函数,把任意长度的数据按照一定规则转换为一个固定长度的数据串(通常用16进制的字符串表示)

1、hashlib的主要用途有两个:

  • 密码的加密

  • 文件一致性校验

2、hashlib的特征以及使用要点:

  • ① bytes类型数据 → 通过hashlib算法 → 固定长度的字符串(16位长度)

  • ② 不同的bytes类型数据转化成的结果一定不同

  • ③ 相同的bytes类型数据转化成的结果一定相同

  • ④ 此转化过程不可逆

16.4.1 密码的普通加密

16.4.1.1 普通加密

我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值

"""-------- 正常加密用法 --------"""

import hashlib

md5 = hashlib.md5()
md5.update('123456'.encode('utf-8'))
print(md5.hexdigest())

# 输出结果:
'e10adc3949ba59abbe56e057f20f883e'
"""---- 验证:相同的bytes数据转化的结果一定相同 ----"""

import hashlib

md5 = hashlib.md5()
md5.update('123456'.encode('utf-8'))
print(md5.hexdigest())

# 输出结果(同一bytes数据多次转化,结果相同):
'e10adc3949ba59abbe56e057f20f883e'


"""---- 验证:不相同的bytes数据转化的结果一定不相同 ----"""

import hashlib

md5 = hashlib.md5()
md5.update('12345'.encode('utf-8'))
print(md5.hexdigest())

# 输出结果:
'827ccb0eea8a706c4c34a16891f84e7b'

16.4.2 密码的加盐加密

比较复杂的加密方式称之为加盐,“固定密码”就是固定的盐

16.4.2.1 加固定的盐
import hashlib

ret = hashlib.md5('固定密码'.encode('utf-8'))
ret.update('a'.encode('utf-8'))
print(ret.hexdigest())

16.4.2.2?加动态的盐
import hashlib

username = 'yuluo'
ret = hashlib.md5(username[::2].encode('utf-8'))
ret.update('a'.encode('utf-8'))
print(ret.hexdigest())

16.4.2.3 sha系列加密

MD5算法是比较常用的一种加密算法,一般的企业用MD5就够用了。但是对安全要求比较高的企业,比如金融行业,MD5加密的方式就不够了,得需要加密方式更高的,比如sha系列,sha1,sha224,sha512等,数字越大,加密的方法越复杂,安全性越高,但是效率就会越慢

"""----- 加固定的盐 -----"""

import hashlib

ret = hashlib.sha384(b'yuluo')
ret.update('a'.encode('utf-8'))
print(ret.hexdigest())


"""----- 加动态的盐 -----"""

import hashlib

ret = hashlib.sha384(b'yuluo'[::2])
ret.update('a'.encode('utf-8'))
print(ret.hexdigest())

17. 内置模块二

17.1 logging模块

17.1.1 函数式简单配置

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

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')   # 严重错误

1、logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:

  • ① filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中
  • ② filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”
  • ③ format:指定handler使用的日志显示格式
  • ④ datefmt:指定日期时间格式
  • ⑤ level:设置rootlogger(后边会讲解具体概念)的日志级别
  • ⑥ stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略

2、format参数中可能用到的格式化串:

%(name)s             # Logger的名字
%(levelno)s          # 数字形式的日志级别
%(levelname)s        # 文本形式的日志级别
%(pathname)s         # 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s         # 调用日志输出函数的模块的文件名
%(module)s           # 调用日志输出函数的模块名
%(funcName)s         # 调用日志输出函数的函数名
%(lineno)d           # 调用日志输出函数的语句所在的代码行
%(created)f          # 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d  # 输出日志信息时的,自Logger创建以来的毫秒数
%(asctime)s          # 字符串形式的当前时间。默认是 “2003-07-08 16:49:45,896”
%(thread)d           # 线程ID。可能没有
%(threadName)s       # 线程名。可能没有
%(process)d          # 进程ID。可能没有
%(message)s          # 用户输出的消息

17.1.2 logger对象配置

logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然,也可以通过fh.setLevel(logging.Debug)单对文件流设置某个级别

import logging
logger = logging.getLogger()

# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log',encoding='utf-8') 

# 再创建一个handler,用于输出到控制台 
ch = logging.StreamHandler() 
formatter = logging.Formatter('%(asctime)s - %(name)s - '
                              '%(levelname)s - %(message)s')
fh.setLevel(logging.DEBUG)

fh.setFormatter(formatter) 
ch.setFormatter(formatter) 
logger.addHandler(fh) #logger对象可以添加多个fh和ch对象 
logger.addHandler(ch) 

logger.debug('logger debug message') 
logger.info('logger info message') 
logger.warning('logger warning message') 
logger.error('logger error message') 
logger.critical('logger critical message')

17.1.3?logger的配置文件

上面这种方式需要创建各种对象,比如logger对象、fileHandler对象、ScreamHandler对象等,比较麻烦,那么下面这种字典的方式,创建logger配置文件,这种才是工作中经常使用的实现日志功能的方法,真正的做到拿来即用(简单改改),如下便是 logging配置

import os
import logging.config

"""----- 定义日志输出格式开始:可选择以下3种版本其一 -----"""

# 标准版 其中name为getlogger指定的名字
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d]' \
                  '[task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'

# 简易版
simple_format = '[%(levelname)s][%(asctime)s]' \
                '[%(filename)s:%(lineno)d]%(message)s'

# 极简版
id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'


"""----- 定义日志输出目录及名称结束 -----"""

# log文件的目录 其中__file__为当前文件名
logfile_dir = os.path.dirname(os.path.abspath(__file__))

# log文件名
logfile_name = 'all2.log'

# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir):
    os.mkdir(logfile_dir)

# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)


"""----- log配置字典 -----"""

LOGGING_DIC = {
    'version': 1,                      # 版本号(本行和下一行均无需改变)
    'disable_existing_loggers': False, # 设置文件中作为设置目标的记录器将采用该设置
    'formatters': {                    # 输出格式,可自行配置如下几种
        'standard': {                  # 输出格式一:标准版
            'format': standard_format
        },
        'simple': {                    # 输出格式二:简易版
            'format': simple_format
        },
    },
    'filters': {},                     # 过滤器(一般无需改变)
    'handlers': {                      # 任务处理(可设置记录到日志/输出到屏幕)
        'console': {                   # 打印到终端的日志,收集debug及以上的日志
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',                 # 打印到屏幕
            'formatter': 'simple'
        },

        'default': {                   # 记录到文件的日志,收集info及以上的日志
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': logfile_path,                         # 日志文件
            'maxBytes': 1024 * 1024 * 5,                      # 日志大小 5M
            'backupCount': 5,
            'encoding': 'utf-8',       # 日志文件的编码,中文log也不乱码
        },
    },
    'loggers': {
        # logging.getLogger(__name__)拿到的logger配置
        '': {
            # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'handlers': ['default', 'console'],
            'level': 'DEBUG',
            'propagate': True,         # 向上(更高level的logger)传递
        },
    },
}

def load_my_logging_cfg():
    logging.config.dictConfig(LOGGING_DIC)    # 导入上面定义的logging配置
    logger = logging.getLogger(__name__)      # 生成一个log实例
    logger.info('It works!')                  # 记录该文件的运行状态

if __name__ == '__main__':
    load_my_logging_cfg()

17.2 collections模块

在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等

17.2.1 namedtuple

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

17.2.1.1 表示集合

我们知道 tuple 可以表示不变集合,例如,一个点的二维坐标就可以表示成:

p = (1, 2)

但是看到(1, 2),很难看出这个tuple是用来表示一个坐标的,这时namedtuple就派上了用场:

from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])   # 此处定义了一个名为'Point'的数据类型
p = Point(1, 2)
print(p)         # 
print(p.x)       # 可以使用点的方式
print(p[0])      # 可以使用索引的方式

# 输出结果:
Point(x=1, y=2)
1
1
"""---------- 类似于格式化时间 ----------"""

import time
struct_time = time.strptime('2022-1-1','%Y-%m-%d')
print(struct_time)
print(struct_time[0])        # 找到了索引为0的 tm_year = 2022
print(struct_time.tm_yday)   # 找到了键为 tm_mday = 1

# 输出结果:
time.struct_time(tm_year=2022, tm_mon=1, tm_mday=1, tm_hour=0, 
                 tm_min=0, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=-1)
2022
1
"""------- 我们利用上方的办法给解决出来 -------"""

from collections import namedtuple
struct_time = namedtuple('struct_time',['tm_year', 'tm_mon', 'tm_mday'])
st = struct_time(2022,1,1)
print(st)

# 输出结果:
struct_time(tm_year=2022, tm_mon=1, tm_mday=1)

17.2.1.2 表示圆

类似的,如果要用坐标和半径表示一个圆,也可以用 namedtuple 定义:

namedtuple('名称', [属性list])

# 例如定义一个在坐标(x,y),半径为r的圆
Circle = namedtuple('Circle', ['x', 'y', 'r'])

17.2.2 deque

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

使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。而deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈

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

from collections import deque
q = deque(['a', 'b', 'c'])
q.append('x')        # 右端添加x
print(q)             # deque(['a', 'b', 'c', 'x'])

q.appendleft('y')    # 左端再添加y
print(q)             # deque(['y', 'a', 'b', 'c', 'x'])

17.2.3 OrderedDict

OrderedDict:有序字典

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序,如果要保持Key的顺序,可以用OrderedDict

from collections import OrderedDict
od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(od)    # OrderedDict的Key是有序的

# 输出结果:
OrderedDict([('a', 1), ('b', 2), ('c', 3)])

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

from collections import OrderedDict
od = OrderedDict()
od['z'] = 1
od['y'] = 2
od['x'] = 3
print(od)
print(od.keys())   # 按照插入的Key的顺序返回

# 输出结果:
OrderedDict([('z', 1), ('y', 2), ('x', 3)])
odict_keys(['z', 'y', 'x'])

17.2.4 defaultdict

defaultdict:带有默认值的字典

我们先来看一道例题,把列表[11, 22, 33, 44, 55, 66, 77, 88, 99],将所有大于66的值保存到一个key中,另外的值保存到另一个key中

"""--------- 常规方法 ---------"""

l1 = [11,22,33,44,55,66,77,88,99]
dic = {}
for i in l1:
    if i < 66:
        if 'key1' not in dic:
            dic['key1'] = []
        dic['key1'].append(i)
    else:
        if 'key2' not in dic:
            dic['key2'] = []
        dic['key2'].append(i)
print(dic)

# 输出结果:
{'key1': [11, 22, 33, 44, 55], 'key2': [66, 77, 88, 99]}
"""--------- defaultdict方法 ---------"""

from collections import defaultdict
l1 = [11,22,33,44,55,66,77,88,99]
dic = defaultdict(list)      # 设置了一个list,此处所设置的必须为可回调的参数
for i in l1:
    if i < 66:
        dic['key1'].append(i)
    else:
        dic['key2'].append(i)
print(dic)

# 输出结果:
defaultdict(<class 'list'>, 
{'key1': [11, 22, 33, 44, 55], 'key2': [66, 77, 88, 99]})

使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict

from collections import defaultdict
dd = defaultdict(lambda: 'N/A')   # 函数也属于可回调的,此处设定的默认值为'N/A'
dd['key1'] = 'abc'
print(dd['key1'])                 # abc  key1存在故返回设定好的'abc'
print(dd['key2'])                 # N/A  key2不存在,返回默认值'N/A'

17.2.5 Counter

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})

文章来源:https://blog.csdn.net/GDYuLuo/article/details/135229392
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。