Python 常用模块(2) 序列化(pickle,shelve,json,configpaser)
主要内容:
一. 序列化概述
二. pickle模块
三. shelve模块
四. json模块(重点!)
五. configpaser模块 一. 序列化概述
1. 序列化: 将字典,列表等内容转换成一个字符串的过程就叫做序列化. 2. 为什么要把其他数据类型转换成字符串?
(1)能够在网络上传输的只能是bytes
(2)能够存储在文件里的只有bytes和str 3. 序列化的目的:
(1)以某种存储形式使自定义对象持久化
(2)将对象从一个地方传递到另一个地方
(3)使程序更具维护性
4. 反序列化:
序列化: str --> 数据结构
反序列化: str <-- 数据结构 5. 在Python中序列化的三种方案:
(1)pickle模块: 可以将Python中的任意数据类型转换成bytes并写入到文件中,同样也可以把文件中写好的bytes转换回Python的数据,这个过程被称为反序列化.
(2)shelve模块: 它是一种简单另类的序列化方案,有一点类似于今后会学习的redis.它可以作为一种小型的数据库来使用.
(3)json模块: 将python中常用的字典,列表转化成字符串.它是目前前后端数据交互使用频率最高的一种数据格式. 二. pickle模块
pickle是把python对象写入到文件中的一种解决方案.写入到文件中的是bytes,它不是给人看的,只有机器可以识别.
pickle可以把python中任意的数据类型序列化. 1. pickle模块中的dumps()方法和loads()方法
注意: dumps()和loads()与文件操作无关 举例说明:
import pickle # 引入模块
class Cat: # 创建类
def __init__(self, name, age):
self.name = name
self.age = age
def catch_mouse(self):
print(self.name, "抓老鼠") cat = Cat("jerry", 18) # 创建一个对象 byte = pickle.dumps(cat) # dumps()方法 --> 序列化一个对象
print(byte) # 打印结果是一堆很长的二进制字符串 new_cat = pickle.loads(byte) # 把二进制字符串反序列化为原来的对象
new_cat.catch_mouse() # 执行结果: jerry 抓老鼠 --> 反序列化之后得到的对象还是原来那个类型的对象
2. pickle模块中的dump()方法和load()方法
注意: dump()方法和load()方法多用于文件的写入\写出操作 举例说明:
import pickle
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def catch_mouse(self):
print(self.name, "抓老鼠") cat = Cat("jerry", 18) # 创建一个对象 with open("cat", mode="wb") as f:
pickle.dump(cat, f) # 把对象cat以二进制字符串的形式写进文件中 with open("cat", mode="rb") as f:
new_cat = pickle.load(f) # 从文件中读取信息,并把信息反序列化为对象
new_cat.catch_mouse() # 对象可以访问类中的方法
3. pickle模块还支持多个对象的写入\写出 举例说明:
import pickle
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def catch_mouse(self):
print(self.name, "抓老鼠") lst = [Cat("jerry", 19), Cat("tommy", 20), Cat("kendy", 21)] with open("cat", mode="wb") as f:
for el in lst:
pickle.dump(el, f) # 把对象序列化并写入文件 with open("cat", mode="rb") as f:
for i in range(len(lst)): # 我们可能事先不知道列表中到底有多少个对象
new_cat = pickle.load(f) # 把文件中的二进制反序列化为对象
new_cat.catch_mouse() # 对象访问catch_mouse()方法
以上操作是有问题的,因为我们在实际情况中是不知道文件内容中有多少个对象的.因此,我们需要换一种操作方式. 举例说明1:
import pickle
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def catch_mouse(self):
print(self.name, "抓老鼠") lst = [Cat("jerry", 19), Cat("tommy", 20), Cat("cendy", 21)] with open("cat", mode="wb") as f:
pickle.dump(lst, f) # 直接把整个列表序列化并写进文件中 with open("cat", mode="rb") as f:
new_lst = pickle.load(f) # 读取文件中的信息,并将其反序列化,拿到一个列表
for el in new_lst: # 遍历整个列表
el.catch_mouse() # 每一个元素都可以访问catch_mouse()方法
举例说明2:
import pickle
dic1 = {(1, 2, 3):{'a', 'b'}, 1:'abc'}
dic2 = {(1, 2, 3):{'a', 'b'}, 2:'abc'}
dic3 = {(1, 2, 3):{'a', 'b'}, 3:'abc'}
dic4 = {(1, 2, 3):{'a', 'b'}, 4:'abc'}
with open ("pickle_file", "wb") as f:
pickle.dump(dic1, f)
pickle.dump(dic2, f)
pickle.dump(dic3, f)
pickle.dump(dic4, f) # 第一种读取方式:
with open("pickle_file", "rb") as f:
ret = pickle.load(f)
print(ret, type(ret))
ret = pickle.load(f)
print(ret, type(ret))
ret = pickle.load(f)
print(ret, type(ret))
ret = pickle.load(f)
print(ret, type(ret))
# ret = pickle.load(f) # EOFError: Ran out of input
# print(ret, type(ret)) # 如果文件中的对象已经全部被load(拿出来反序列化)了,此时再次load就会报错 # 以上代码执行结果:
# {(1, 2, 3): {'b', 'a'}, 1: 'abc'} <class 'dict'>
# {(1, 2, 3): {'b', 'a'}, 2: 'abc'} <class 'dict'>
# {(1, 2, 3): {'b', 'a'}, 3: 'abc'} <class 'dict'>
# {(1, 2, 3): {'b', 'a'}, 4: 'abc'} <class 'dict'> # 改进后的第二种读取方式:
with open("pickle_file", "rb") as f:
while True:
try:
ret = pickle.load(f)
print(ret, type(ret))
except EOFError: # 异常被捕获了
break
对pickle模块的总结:
(1)pickle只能在python中使用,它只支持python这门语言,跨平台性较差.
(2)pickle序列化支持在python中的几乎所有数据类型.
(3)pickle中的dumps方法序列化的结果一定是字节.
(4)在进行文件操作时,需要用rb和wb模式打开文件.
(5)可以dump多个对象到文件中,也可以从文件中load出来多个对象(load次数超过对象个数会报错,注意捕获异常). 三. shelve模块
shelve提供python的持久化操作,即把数据写到硬盘上.
shelve的操作方式与字典非常相似,可以把它看作是"文件的字典式操作". 1. 增加
import shelve
helf = shelve.open("shelve_test1")
# print(shelf["jay"]) # 报错,因为文件中还没有"jay"的信息 shelf["jay"] = "周杰伦" # 执行新增
print(shelf["jay"]) # 打印结果: 周杰伦 --> 新增成功 shelf.close()
2. 修改
import shelve
shelf = shelve.open("shelve_test1")
print(shelf["jay"])
# 像操作字典一样直接进行修改:
shelf["jay"] = {"name": "周杰伦", "age": 18, "hobby": "唱歌"}
print(shelf["jay"])
shelf.close()
# 执行结果:
# 周杰伦
# {'name': '周杰伦', 'age': 18, 'hobby': '唱歌'} 尝试修改{'name': '周杰伦', 'age': 18, 'hobby': '唱歌'}这个字典中的内容:
shelf = shelve.open("shelve_test1")
shelf["jay"]["name"] = "王力宏" # 尝试修改
shelf.close()
shelf = shelve.open("shelve_test1")
print(shelf["jay"]["name"]) # 查看我们修改的内容
shelf.close()
# 打印结果: 周杰伦 --> 修改失败
解决方案如下:
shelf = shelve.open("shelve_test1", writeback=True)
shelf["jay"]["name"] = "王力宏" # 再次尝试修改
shelf.close()
shelf = shelve.open("shelve_test1")
print(shelf["jay"]["name"]) # 查看我们修改的内容
shelf.close()
# 打印结果: 王力宏 --> 修改成功
writeback=True可以动态地把我们修改的信息写入到文件中,而且它还可以删除数据,就像字典一样 3. 删除
shelf = shelve.open("shelve_test1", writeback=True)
del shelf["jay"]
shelf.close()
shelf = shelve.open("shelve_test1")
print(shelf["jay"]) # 打印结果: 报错 --> 因为之前已经把"jay"的数据给删除了
shelf.close()
4. 查找
shelf = shelve.open("shelve_test1", writeback=True)
shelf["乐坛半壁江山"] = "汪峰"
shelf["华仔"] = "刘德华"
shelf["星爷"] = "周星驰"
shelf.close() # 遍历文件拿到所有key
shelf = shelve.open("shelve_test1") for k in shelf:
print(k) # 拿到所有key for k in shelf.keys():
print(k) # 拿到所有key for v in shelf.values():
print(v) # 拿到所有value for k, v in shelf.items():
print(k, v) # 拿到所有key和value shelf.close()
四. json模块
json模块提供了四个功能: 序列化(dumps和dump), 反序列化(loads和load) 如下实例:
import json
dic = {'key': 'value', 'key2': 'value2'} ret = json.dumps(dic) # 序列化
print(dic, type(dic)) # {'key': 'value', 'key2': 'value2'} <class 'dict'>
print(ret, type(ret)) # {"key": "value", "key2": "value2"} <class 'str'> res = json.loads(ret) # 反序列化
print(res, type(res)) # {'key': 'value', 'key2': 'value2'} <class 'dict'>
# json能够序列化的数据有什么特点?观察下面几个示例,分析结果.
# 特点1: 字典的key是整型,经过序列化和反序列化之后变成了字符串类型
# 特点2: 字典的value是元组, 经过序列化和反序列化之后变成了列表类型
dic = {1:[1,2,3], 2:(4,5,'aa')}
ret = json.dumps(dic) # 序列化
print(dic, type(dic)) # {1: [1, 2, 3], 2: (4, 5, 'aa')} <class 'dict'>
print(ret, type(ret)) # {"1": [1, 2, 3], "2": [4, 5, "aa"]} <class 'str'> res = json.loads(ret) # 反序列化
print(res, type(res)) # {'1': [1, 2, 3], '2': [4, 5, 'aa']} <class 'dict'> # 特点3: set集合类型不能被json序列化
# 特点4: 字典的键必须是字符串才能被json序列化
s = {1, 2, "aaa"}
json.dumps(s) # 报错: TypeError: Object of type 'set' is not JSON serializable
json.dumps({(1,2,3):123}) # 报错: TypeError: keys must be a string
总结: json在所有的语言之间都通用:即在python中json序列化后的数据,把它拿到java中也可以反序列化,反之亦然.
可以认为,json序列化后的数据,在其他语言中也能够反序列化回来,所有语言都可以识别"json序列化后的数据".
由此也导致json能够处理的数据非常有限,只有 字符串,列表,字典,数字 这几种类型,而且字典中的key只能是字符串.
# 向文件中写入字典
import json
dic = {'key' : 'value','key2' : 'value2'}
ret = json.dumps(dic) # 序列化(这里是将序列化结果全部写入内存,下面的代码再从内存中读取全部结果并写入文件)
with open("json_file", "a") as f:
f.write(ret) # 从内存中读取数据,并写入文件中 # 从文件中读取字典
with open ("json_file", "r") as f:
str_dic = f.read() # 读取全部文件内容并将其写入内存
dic = json.loads(str_dic) # 将内存中的字符串反序列化
print(dic) # 打印结果: {'key': 'value', 'key2': 'value2'} # dump和load是直接操作文件的,如下示例:
dic = {'key1' : 'value1','key2' : 'value2'}
with open('json_file', 'a') as f:
json.dump(dic, f) # 把dic序列化并写入文件json_file中 with open('json_file', 'r') as f:
dic = json.load(f) # 把文件内容反序列化为字典
print(dic) # {'key1': 'value1', 'key2': 'value2'}
总结: 如果我们是进行文件相关的操作(读/写),那么可以用dump和load.如果是处理网络上传输的数据是,由于此时数据都是在内存中,这就要用到dumps和loads了.
# 特点5: 不支持连续的存取
dic = {'key1':'value1', 'key2':'value2'}
with open("json_file", "a") as f:
json.dump(dic, f)
json.dump(dic, f)
json.dump(dic, f) with open("json_file", "r") as f:
dic = json.load(f)
print(dic.keys())
总结: 上面程序中虽然成功通过dump多次向文件中存入3个字典,但是load会报错. 也就是说load只能读取"存一个字典"的文件,嵌套字典也可以,但最外层只能是一个.
# 解决办法
dic = {'key1':'value1', 'key2':'value2'}
with open("json_file", "a") as f:
str_dic = json.dumps(dic)
f.write(str_dic + "\n")
str_dic = json.dumps(dic)
f.write(str_dic + "\n")
str_dic = json.dumps(dic)
f.write(str_dic + "\n") with open("json_file", "r") as f:
for line in f:
dic = json.loads(line.strip())
print(dic) # 执行结果:
# {'key1': 'value1', 'key2': 'value2'}
# {'key1': 'value1', 'key2': 'value2'}
# {'key1': 'value1', 'key2': 'value2'}
综上所述:
json的dumps和loads -- 在内存中做数据转换:
dumps(序列化) --> 数据类型 转成 字符串
loads(反序列化) --> 字符串 转成 数据类型
json的dump和load -- 直接将数据类型写入文件,直接从文件中读出数据类型:
dump(序列化) --> 把数据类型序列化并写入文件
load(反序列化) --> 从文件中读出内容并将其反序列化为数据类型 json是所有语言都通用的一种序列化格式,只支持列表,字典,字符串,数字,并且字典的key必须是字符串.
# ensure_ascii 关键字参数
dic = {"key":"你好}
print(json.dumps(dic)) # {"key": "\u4f60\u597d"}
print(json.dumps(dic, ensure_ascii=False)) # {"key": "你好"}
# json 的格式化输出
data = {"username":["赵日天", "二愣子"], "gender":"male", "age":16}
json_dic = json.dumps(data, sort_keys=True, indent=4, separators=(',',':'), ensure_ascii=False)
print(json_dic)
# 执行结果:
# {
# "age":16,
# "gender":"male",
# "username":[
# "赵日天",
# "二愣子"
# ]
# }
五. configparser模块
该模块适⽤于配置⽂件的格式与windows下的ini⽂件类似,可以包含⼀个或多个节(section),每个节
可以有多个参数(键=值).
import configparser
config = configparser.ConfigParser()
config['DEFAULT'] = {
"sleep": 1000,
"session_time_out": 30,
"user_alive": 999999
}
config['TEST-DB'] = {
"db_ip": "192.168.17.189",
"port": "",
"u_name": "root",
"u_pwd": ""
}
config['168-DB'] = {
"db_ip": "152.163.18.168",
"port": "",
"u_name": "root",
"u_pwd": ""
}
config['173-DB'] = {
"db_ip": "152.163.18.173",
"port": "",
"u_name": "root",
"u_pwd": ""
}
f = open("db.ini", mode="w")
config.write(f) # 写⼊⽂件
f.flush()
f.close()
# 读取⽂件信息:
config = configparser.ConfigParser()
config.read("db.ini") # 读取⽂件
print(config.sections()) # 获取到section章节, DEFAULT是给每个章节都配备的信息
print(config.get("DEFAULT", "SESSION-TIME-OUT")) # 从xxx章节中读取到xxx信息 # 也可以像字典⼀样操作
print(config["TEST-DB"]['DB_IP'])
print(config["173-DB"]["db_ip"]) for k in config['168-DB']:
print(k) for k, v in config["168-DB"].items():
print(k, v) print(config.options('168-DB')) # 同for循环,找到'168-DB'下所有键
print(config.items('168-DB')) # 找到'168-DB'下所有键值对
print(config.get('168-DB','db_ip')) # 152.163.18.168 get⽅法Section下的key对应的value # 增删改操作:
# 先读取,然后修改,最后写回⽂件
config = configparser.ConfigParser()
config.read("db.ini") # 读取⽂件
# 添加⼀个章节
config.add_section("189-DB")
config["189-DB"] = {
"db_ip": "167.76.22.189",
"port": "",
"u_name": "root",
"u_pwd": ""
}
# 修改信息
config.set("168-DB", "db_ip", "10.10.10.168")
# 删除章节
config.remove_section("173-DB")
# 删除元素信息
config.remove_option("168-DB", "u_name")
# 写回⽂件
config.write(open("db.ini", mode="w"))
Python 常用模块(2) 序列化(pickle,shelve,json,configpaser)的更多相关文章
- Learning-Python【20】:Python常用模块(3)—— shelve、pickle、json、xml、configparser
什么是序列化/反序列化? 序列化就是将内存中的数据结构转换成一种中间格式存储到硬盘或者基于网络传输,反序列化就是硬盘中或者网络中传来的一种数据格式转换成内存中数据结构 为什么要有序列化/反序列化? 1 ...
- python 序列化 pickle shelve json configparser
1. 什么是序列化 我们把变量从内存中变成可存储或传输的过程称之为序列化. 序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上. 反过来,把变量内容从序列化的对象重新读到内存里称 ...
- 各类模块的粗略总结(time,re,os,sys,序列化,pickle,shelve.#!json )
***collections 扩展数据类型*** ***re 正则相关操作 正则 匹配字符串*** ***time 时间相关 三种格式:时间戳,格式化时间(字符串),时间元组(结构化时间).***`` ...
- 序列化 pickle shelve json configparser
模块pickle(皮考) dumps(当破死)序列化. 把对象转化成bytes loads(楼死) 反序列化. 吧bytes转化成对象 dic = {"jay": "周杰 ...
- python 常用模块 time random os模块 sys模块 json & pickle shelve模块 xml模块 configparser hashlib subprocess logging re正则
python 常用模块 time random os模块 sys模块 json & pickle shelve模块 xml模块 configparser hashlib subprocess ...
- (转)python常用模块(模块和包的解释,time模块,sys模块,random模块,os模块,json和pickle序列化模块)
阅读目录 1.1.1导入模块 1.1.2__name__ 1.1模块 什么是模块: 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代 ...
- python常用模块之json、pickle模块
python常用模块之json.pickle模块 什么是序列化? 序列化就是把内存里的数据类型转换成字符,以便其能存储到硬盘或者通过网络进行传输,因为硬盘或网络传输时只接受bytes. 为什么要序列化 ...
- python常用模块之shelve模块
python常用模块之shelve模块 shelve模块是一个简单的k,v将内存中的数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据类型 我们在上面讲json.pickle ...
- Day05 - Python 常用模块
1. 模块简介 模块就是一个保存了 Python 代码的文件.模块能定义函数,类和变量.模块里也能包含可执行的代码. 模块也是 Python 对象,具有随机的名字属性用来绑定或引用. 下例是个简单的模 ...
随机推荐
- golang 中Pointers Vs References
原文: https://spf13.com/post/go-pointers-vs-references/ Pointers Vs References Some languages includin ...
- JavaScript实现数据的双向绑定
接触到Angulr.js和Vue.js后,提到最多的就是双向绑定 下面将用JavaScript实现数据的双向绑定 <!DOCTYPE html> <html> <head ...
- GPU driven pipeline in metal
https://developer.apple.com/documentation/metal/dynamic_terrain_with_argument_buffers?language=objc ...
- Mybatis一对一和一对多配置
作者:夕下奕林 问题描述 现在有三张数据表,表名为orders,orderdetail,items,分别表示订单,订单详情,商品. 其中一个订单包含多个订单详情,表示订单中的不同个具体的商品,订单详情 ...
- 2018多校第十场 HDU 6430 (线段树合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6430 题意:一棵树上每个节点权值为v[i],每个节点的heard值是:以它为LCA的两个节点的GCD的 ...
- Java日期工具类DateUtils详解(转)
jar包 appache下的 common-lang3 一. 对指定的日期新增年.月.周.日.小时.分钟.秒.毫秒 public static Date addDays(Date date, int ...
- 脚本实现PXE装机
#!/bin/bash read -p "请输入您的装机服务器:" ip read -p "请输入您想要的ip最小值(1-255):" min read -p ...
- Luogu P1066 2^k进制数 组合数学
分两种情况:$k|n$和$k$不整除$n$ 如果$k|n$,那么长度为$n$的二进制数就能被恰好分成$n/k$个块:所以若某个数长度是$x$个块,由于每个块内能填不同的$2^k-1$个数,那么就有$C ...
- boost 函数与回调
result_of 含义:result_of可以帮助程序员确定一个调用表达式的返回类型,主要用于泛型编程和其他boost库组件,它已经被纳入TR1 头文件:<boost/utility/resu ...
- MySQL Innodb引擎和MyIASM引擎的区别
Innodb引擎 Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别.该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL ...