python 序列化 pickle shelve json configparser

1. 什么是序列化

 我们把变量从内存中变成可存储或传输的过程称之为序列化。

 序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。

 反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。

 举例:大家应该都玩过魔兽争霸,应该知道该游戏有一个存档的功能,我每次不想玩得时候就可以存档,然后再玩得时候我们根本不需要重新开始玩,只需要读档就可以了。我们现在学习的事面向对象的思想,那么在我们眼中不管是我们的游戏角色还是游戏中的怪物、装备等等都可以看成是 一个个的对象,进行简单的分析。

角色对象(包含等级、性别、经验值、HP、MP等等属性) 
武器对象(包含武器的类型、武器的伤害、武器附加的能力值等等属性) 
怪物对象(包含等级、经验值、攻击、怪物类型等等) 
于是玩游戏过程变的非常有意思了,创建游戏角色就好像是创建了一个角色对象,拿到武器就好像创建了一个武器对象,遇到的怪物、NPC等等都是对象了。 
然后再用学 过的知识进行分析,我们发现对象的数据都是保存在内存中的,应该都知道内存的数据在断电以后是会消失的,但是我们的游戏经过存档以后,就算你关机了几天, 再进入游戏的时候,读取你的存档发现你在游戏中的一切都还在呢,奇怪了,明明内存中的数据已经没有了啊,这是为什么呢?于是再仔细考虑,电脑中有硬盘这个 东西在断电以后保存的数据是不会丢的(要是由于断电导致的硬盘损坏了,没有数据了,哈哈,不在此考虑中)。那么应该很容易的想到这些数据是被保存在硬盘中 了。没错!这就是对象的持久化,也就是我们今天要讲的对象的序列化。那么反序列化就很好理解了就是将存放在硬盘中的信息再读取出来形成对象。

 

---如何序列化?

  在python中提供了两个模块可进行序列化。分别是pickle和json。


2. pickle(重点)

用于序列化的两个模块
  json:用于字符串和Python数据类型间进行转换
  pickle: 用于python特有的类型和python的数据类型间进行转换
  json提供四个功能:dumps,dump,loads,load
  pickle提供四个功能:dumps,dump,loads,load

pickle可以存储什么类型的数据呢?

  1. 所有python支持的原生类型:布尔值,整数,浮点数,复数,字符串,字节,None。
  2. 由任何原生类型组成的列表,元组,字典和集合。
  3. 函数,类,类的实例

pickle模块中常用的方法有:

    1. pickle.dump(obj, file, protocol=None,)

    必填参数obj表示将要封装的对象

    必填参数file表示obj要写入的文件对象,file必须以二进制可写模式打开,即“wb”

    可选参数protocol表示告知pickler使用的协议,支持的协议有0,1,2,3,默认的协议是添加在Python 3中的协议3。   

  • Protocol version 0 is the original “human-readable” protocol and is backwards compatible with earlier versions of Python.
  • Protocol version 1 is an old binary format which is also compatible with earlier versions of Python.
  • Protocol version 2 was introduced in Python 2.3. It provides much more efficient pickling of new-style classes. Refer to PEP 307 for information about improvements brought by protocol 2.
  • Protocol version 3 was added in Python 3.0. It has explicit support for bytes objects and cannot be unpickled by Python 2.x. This is the default protocol, and the recommended protocol when compatibility with other Python 3 versions is required.
  • Protocol version 4 was added in Python 3.4. It adds support for very large objects, pickling more kinds of objects, and some data format optimizations. Refer to PEP 3154 for information about improvements brought by protocol 4. 

    2. pickle.load(file,*,fix_imports=True, encoding="ASCII", errors="strict")

    必填参数file必须以二进制可读模式打开,即“rb”,其他都为可选参数

    3. pickle.dumps(obj):以字节对象形式返回封装的对象,不需要写入文件中

    4. pickle.loads(bytes_object): 从字节对象中读取被封装的对象,并返回

 pickle模块可能出现三种异常:

    1. PickleError:封装和拆封时出现的异常类,继承自Exception

    2. PicklingError: 遇到不可封装的对象时出现的异常,继承自PickleError

    3. UnPicklingError: 拆封对象过程中出现的异常,继承自PickleError

应用:

复制代码
复制代码
1 # dumps功能
2 import pickle
3 data = ['aa', 'bb', 'cc']  
4 # dumps 将数据通过特殊的形式转换为只有python语言认识的字符串
5 p_str = pickle.dumps(data)
6 print(p_str)            
7 b'\x80\x03]q\x00(X\x02\x00\x00\x00aaq\x01X\x02\x00\x00\x00bbq\x02X\x02\x00\x00\x00ccq\x03e.
复制代码
复制代码
1 # loads功能
2 # loads  将pickle数据转换为python的数据结构
3 mes = pickle.loads(p_str)
4 print(mes)
5 ['aa', 'bb', 'cc']
1 # dump功能
2 # dump 将数据通过特殊的形式转换为只有python语言认识的字符串,并写入文件
3 with open('D:/tmp.pk', 'w') as f:
4     pickle.dump(data, f)
1 # load功能
2 # load 从数据文件中读取数据,并转换为python的数据结构
3 with open('D:/tmp.pk', 'r') as f:
4     data = pickle.load(f)


3. shelve

这几天接触了Python中的shelve这个module,感觉比pickle用起来更简单一些,它也是一个用来持久化Python对象的简单工具。当我们写程序的时候如果不想用关系数据库那么重量级的东东去存储数据,不妨可以试试用shelve。shelf也是用key来访问的,使用起来和字典类似。shelve其实用anydbm去创建DB并且管理持久化对象的。

 

创建一个新的shelf

直接使用shelve.open()就可以创建了

复制代码
1 import shelve
2 
3 s = shelve.open('test_shelf.db')
4 try:
5     s['key1'] = { 'int': 10, 'float':9.5, 'string':'Sample data' }
6 finally:
7     s.close()
复制代码

 

如果想要再次访问这个shelf,只需要再次shelve.open()就可以了,然后我们可以像使用字典一样来使用这个shelf

复制代码
1 import shelve
2 
3 s = shelve.open('test_shelf.db')
4 try:
5     existing = s['key1']
6 finally:
7     s.close()
8 
9 print existing
复制代码

 

当我们运行以上两个py,我们将得到如下输出:

$ python shelve_create.py
$ python shelve_existing.py

{'int': 10, 'float': 9.5, 'string': 'Sample data'}

 

dbm这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB:

复制代码
1 import shelve
2 
3 s = shelve.open('test_shelf.db', flag='r')
4 try:
5     existing = s['key1']
6 finally:
7     s.close()
8 
9 print existing
复制代码

当我们的程序试图去修改一个以只读方式打开的DB时,将会抛一个访问错误的异常。异常的具体类型取决于anydbm这个模块在创建DB时所选用的DB。

 

写回(Write-back)

由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。

复制代码
 1 import shelve
 2 
 3 s = shelve.open('test_shelf.db')
 4 try:
 5     print s['key1']
 6     s['key1']['new_value'] = 'this was not here before'
 7 finally:
 8     s.close()
 9 
10 s = shelve.open('test_shelf.db', writeback=True)
11 try:
12     print s['key1']
13 finally:
14     s.close()
复制代码

上面这个例子中,由于一开始我们使用了缺省参数shelve.open()了,因此第6行修改的值即使我们s.close()也不会被保存。

执行结果如下:

$ python shelve_create.py
$ python shelve_withoutwriteback.py

{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'float': 9.5, 'string': 'Sample data'}

 

所以当我们试图让shelve去自动捕获对象的变化,我们应该在打开shelf的时候将writeback设置为True。当我们将writeback这个flag设置为True以后,shelf将会将所有从DB中读取的对象存放到一个内存缓存。当我们close()打开的shelf的时候,缓存中所有的对象会被重新写入DB。

复制代码
 1 import shelve
 2 
 3 s = shelve.open('test_shelf.db', writeback=True)
 4 try:
 5     print s['key1']
 6     s['key1']['new_value'] = 'this was not here before'
 7     print s['key1']
 8 finally:
 9     s.close()
10 
11 s = shelve.open('test_shelf.db', writeback=True)
12 try:
13     print s['key1']
14 finally:
15     s.close()
复制代码

writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。

复制代码
1 $ python shelve_create.py
2 $ python shelve_writeback.py
3 
4 {'int': 10, 'float': 9.5, 'string': 'Sample data'}
5 {'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}
6 {'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}
复制代码

 

最后再来个复杂一点的例子:

复制代码
 1 #!/bin/env python
 2 
 3 import time
 4 import datetime
 5 import md5
 6 import shelve
 7 
 8 LOGIN_TIME_OUT = 60
 9 db = shelve.open('user_shelve.db', writeback=True)
10 
11 def newuser():
12     global db
13     prompt = "login desired: "
14     while True:
15         name = raw_input(prompt)
16         if name in db:
17             prompt = "name taken, try another: "
18             continue
19         elif len(name) == 0:
20             prompt = "name should not be empty, try another: "
21             continue
22         else:
23             break
24     pwd = raw_input("password: ")
25     db[name] = {"password": md5_digest(pwd), "last_login_time": time.time()}
26     #print '-->', db
27 
28 def olduser():
29     global db
30     name = raw_input("login: ")
31     pwd = raw_input("password: ")
32     try:
33         password = db.get(name).get('password')
34     except AttributeError, e:
35         print "\033[1;31;40mUsername '%s' doesn't existed\033[0m" % name
36         return
37     if md5_digest(pwd) == password:
38         login_time = time.time()
39         last_login_time = db.get(name).get('last_login_time')
40         if login_time - last_login_time < LOGIN_TIME_OUT:
41             print "\033[1;31;40mYou already logged in at: <%s>\033[0m" % datetime.datetime.fromtimestamp(last_login_time).isoformat()
42 
43         db[name]['last_login_time'] = login_time
44         print "\033[1;32;40mwelcome back\033[0m", name
45     else:
46         print "\033[1;31;40mlogin incorrect\033[0m"
47 
48 def md5_digest(plain_pass):
49    return md5.new(plain_pass).hexdigest()
50 
51 def showmenu():
52     #print '>>>', db
53     global db
54     prompt = """
55 (N)ew User Login
56 (E)xisting User Login
57 (Q)uit
58 Enter choice: """
59     done = False
60     while not done:
61         chosen = False
62         while not chosen:
63             try:
64                 choice = raw_input(prompt).strip()[0].lower()
65             except (EOFError, KeyboardInterrupt):
66                 choice = "q"
67             print "\nYou picked: [%s]" % choice
68             if choice not in "neq":
69                 print "invalid option, try again"
70             else:
71                 chosen = True
72 
73         if choice == "q": done = True
74         if choice == "n": newuser()
75         if choice == "e": olduser()
76     db.close()
77 
78 if __name__ == "__main__":
79     showmenu()
复制代码


4. json(重点)

JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。JSON的数据格式其实就是python里面的字典格式,里面可以包含方括号括起来的数组,也就是python里面的列表。

在python中,有专门处理json格式的模块—— json 和 picle模块

  Json   模块提供了四个方法: dumps、dump、loads、load

pickle 模块也提供了四个功能:dumps、dump、loads、load
 
一. dumps 和 dump:
 dumps和dump   序列化方法
       dumps只完成了序列化为str,
       dump必须传文件描述符,将序列化的str保存到文件中
 
查看源码:
def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        default=None, sort_keys=False, **kw):
    # Serialize ``obj`` to a JSON formatted ``str``.
    # 序列号 “obj” 数据类型 转换为 JSON格式的字符串 
def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        default=None, sort_keys=False, **kw):
    """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
    ``.write()``-supporting file-like object).
     我理解为两个动作,一个动作是将”obj“转换为JSON格式的字符串,还有一个动作是将字符串写入到文件中,也就是说文件描述符fp是必须要的参数 """

 

示例代码:

复制代码
>>> import json
>>> json.dumps([])    # dumps可以格式化所有的基本数据类型为字符串
'[]'
>>> json.dumps(1)    # 数字
'1'
>>> json.dumps('1')   # 字符串
'"1"'
>>> dict = {"name":"Tom", "age":23}  
>>> json.dumps(dict)     # 字典
'{"name": "Tom", "age": 23}'
复制代码
a = {"name":"Tom", "age":23}
with open("test.json", "w", encoding='utf-8') as f:
    # indent 超级好用,格式化保存字典,默认为None,小于0为零个空格
    f.write(json.dumps(a, indent=4))
    # json.dump(a,f,indent=4)   # 和上面的效果一样

保存的文件效果:

 

二. loads 和 load 

loads和load  反序列化方法

       loads 只完成了反序列化,
       load 只接收文件描述符,完成了读取文件和反序列化

 

 查看源码:

def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
    """Deserialize ``s`` (a ``str`` instance containing a JSON document) to a Python object.
       将包含str类型的JSON文档反序列化为一个python对象"""
def load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
    """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing a JSON document) to a Python object.
        将一个包含JSON格式数据的可读文件饭序列化为一个python对象"""

 

实例:

>>> json.loads('{"name":"Tom", "age":23}')
{'age': 23, 'name': 'Tom'}
复制代码
import json
with open("test.json", "r", encoding='utf-8') as f:
    aa = json.loads(f.read())
    f.seek(0)
    bb = json.load(f)    # 与 json.loads(f.read())
print(aa)
print(bb)

# 输出:
{'name': 'Tom', 'age': 23}
{'name': 'Tom', 'age': 23}
复制代码

三. json 和 picle 模块

 json模块和picle模块都有  dumps、dump、loads、load四种方法,而且用法一样。

不用的是json模块序列化出来的是通用格式,其它编程语言都认识,就是普通的字符串,

而picle模块序列化出来的只有python可以认识,其他编程语言不认识的,表现为乱码

不过picle可以序列化函数,但是其他文件想用该函数,在该文件中需要有该文件的定义(定义和参数必须相同,内容可以不同)

四. python对象(obj) 与json对象的对应关系

复制代码
    +-------------------+---------------+
    | Python            | JSON          |
    +===================+===============+
    | dict              | object        |
    +-------------------+---------------+
    | list, tuple       | array         |
    +-------------------+---------------+
    | str               | string        |
    +-------------------+---------------+
    | int, float        | number        |
    +-------------------+---------------+
    | True              | true          |
    +-------------------+---------------+
    | False             | false         |
    +-------------------+---------------+
    | None              | null          |
    +-------------------+---------------+
复制代码

 

 五. 总结

 1. json序列化方法:

          dumps:无文件操作            dump:序列化+写入文件

  2. json反序列化方法:

          loads:无文件操作              load: 读文件+反序列化

  3. json模块序列化的数据 更通用

      picle模块序列化的数据 仅python可用,但功能强大,可以序列号函数

  4. json模块可以序列化和反序列化的  数据类型 见  python对象(obj) 与json对象的对应关系表

  5. 格式化写入文件利用  indent = 4 


5. configparser模块

 

一、ConfigParser简介

 

ConfigParser 是用来读取配置文件的包。配置文件的格式如下:中括号“[ ]”内包含的为section。section 下面为类似于key-value 的配置内容。

 

复制代码
[db]
db_host = 127.0.0.1
db_port = 69
db_user = root
db_pass = root
host_port = 69

[concurrent]
thread = 10
processor = 20
复制代码

 

括号“[ ]”内包含的为section。紧接着section 为类似于key-value 的options 的配置内容。

 

二、ConfigParser 初始化对象

 

使用ConfigParser 首选需要初始化实例,并读取配置文件:

 

import configparser
config = configparser.ConfigParser()
config.read("ini", encoding="utf-8")

 

三、ConfigParser 常用方法

 

1、获取所用的section节点

 

复制代码
# 获取所用的section节点
import configparser
config = configparser.ConfigParser()
config.read("ini", encoding="utf-8")
print(config.sections())
#运行结果
# ['db', 'concurrent']
复制代码

 

2、获取指定section 的options。即将配置文件某个section 内key 读取到列表中:

 

复制代码
import configparser
config = configparser.ConfigParser()
config.read("ini", encoding="utf-8")
r = config.options("db")
print(r)
#运行结果
# ['db_host', 'db_port', 'db_user', 'db_pass', 'host_port']
复制代码

 

3、获取指点section下指点option的值

 

复制代码
import configparser
config = configparser.ConfigParser()
config.read("ini", encoding="utf-8")
r = config.get("db", "db_host")
# r1 = config.getint("db", "k1") #将获取到值转换为int型
# r2 = config.getboolean("db", "k2" ) #将获取到值转换为bool型
# r3 = config.getfloat("db", "k3" ) #将获取到值转换为浮点型
print(r)
#运行结果
# 127.0.0.1
复制代码

 

4、获取指点section的所用配置信息

 

复制代码
import configparser
config = configparser.ConfigParser()
config.read("ini", encoding="utf-8")
r = config.items("db")
print(r)
#运行结果
#[('db_host', '127.0.0.1'), ('db_port', '69'), ('db_user', 'root'), ('db_pass', 'root'), ('host_port', '69')]
复制代码

 

5、修改某个option的值,如果不存在则会出创建

 

复制代码
# 修改某个option的值,如果不存在该option 则会创建
import configparser
config = configparser.ConfigParser()
config.read("ini", encoding="utf-8")
config.set("db", "db_port", "69")  #修改db_port的值为69
config.write(open("ini", "w"))
复制代码

 

复制代码
[db]
db_host = 127.0.0.1
db_port = 69
db_user = root
db_pass = root

[concurrent]
thread = 10
processor = 20
复制代码

 

6、检查section或option是否存在,bool值

 

import configparser
config = configparser.ConfigParser()
config.has_section("section") #是否存在该section
config.has_option("section", "option")  #是否存在该option

 

7、添加section 和 option

 

复制代码
import configparser
config = configparser.ConfigParser()
config.read("ini", encoding="utf-8")
if not config.has_section("default"):  # 检查是否存在section
    config.add_section("default")
if not config.has_option("default", "db_host"):  # 检查是否存在该option
    config.set("default", "db_host", "1.1.1.1")
config.write(open("ini", "w"))
复制代码

 

复制代码
[db]
db_host = 127.0.0.1
db_port = 69
db_user = root
db_pass = root

[concurrent]
thread = 10
processor = 20

[default]
db_host = 1.1.1.1
复制代码

 

8、删除section 和 option

 

import configparser
config = configparser.ConfigParser()
config.read("ini", encoding="utf-8")
config.remove_section("default") #整个section下的所有内容都将删除
config.write(open("ini", "w"))

 

复制代码
[db]
db_host = 127.0.0.1
db_port = 69
db_user = root
db_pass = root

[concurrent]
thread = 10
processor = 20
复制代码

 

9、写入文件

 

以下的几行代码只是将文件内容读取到内存中,进过一系列操作之后必须写回文件,才能生效。

 

import configparser
config = configparser.ConfigParser()
config.read("ini", encoding="utf-8")

 

写回文件的方式如下:(使用configparser的write方法)

 

config.write(open("ini", "w"))

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园的建设目标是通过数据整合、全面共享,实现校园内教学、科研、管理、服务流程的数字化、信息化、智能化和多媒体化,以提高资源利用率和管理效率,确保校园安全。 智慧校园的建设思路包括构建统一支撑平台、建立完善管理体系、大数据辅助决策和建设校园智慧环境。通过云架构的数据中心与智慧的学习、办公环境,实现日常教学活动、资源建设情况、学业水平情况的全面统计和分析,为决策提供辅助。此外,智慧校园还涵盖了多媒体教学、智慧录播、电子图书馆、VR教室等多种教学模式,以及校园网络、智慧班牌、校园广播等教务管理功能,旨在提升教学品质和管理水平。 智慧校园的详细方案设计进一步细化了教学、教务、安防和运维等多个方面的应用。例如,在智慧教学领域,通过多媒体教学、智慧录播、电子图书馆等技术,实现教学资源的共享和教学模式的创新。在智慧教务方面,校园网络、考场监控、智慧班牌等系统为校园管理提供了便捷和高效。智慧安防系统包括视频监控、一键报警、阳光厨房等,确保校园安全。智慧运维则通过综合管理平台、设备管理、能效管理和资产管理,实现校园设施的智能化管理。 智慧校园的优势和价值体现在个性化互动的智慧教学、协同高效的校园管理、无处不在的校园学习、全面感知的校园环境和轻松便捷的校园生活等方面。通过智慧校园的建设,可以促进教育资源的均衡化,提高教育质量和管理效率,同时保障校园安全和提升师生的学习体验。 总之,智慧校园解决方案通过整合现代信息技术,如云计算、大数据、物联网和人工智能,为教育行业带来了革命性的变革。它不仅提高了教育的质量和效率,还为师生创造了一个更加安全、便捷和富有智慧的学习与生活环境。
Pythonpickle模块是用来实现序列化的,即将Python中的对象转换成字节流,方便存储和传输。pickle模块支持多种协议,其中协议0是最早的版本,协议1和协议2是Pyhton2中引入的,协议3是Python3.0中引入的,协议4是Python3.4中引入的,每个协议都有其特点和适用范围。 下面我们来详细了解一下pickle模块的使用方法和各个协议的特点。 ## 基本用法 pickle模块提供了dumps、dump、loads和load四个函数,分别用来进行序列化和反序列化操作。其中dumps和loads函数可以直接将对象转换成字节流或将字节流转换成对象,而dump和load函数则可以将对象序列化到文件或从文件中反序列化对象。 ### 序列化Python对象转换成字节流的过程称为序列化,可以使用dumps函数实现: ```python import pickle data = {'name': 'Tom', 'age': 18, 'gender': 'male'} bytes_data = pickle.dumps(data) print(bytes_data) ``` 输出结果为: ``` b'\x80\x04\x95\x17\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x03Tom\x94\x8c\x03age\x94K\x12\x8c\x06gender\x94\x8c\x04male\x94u.' ``` 可以看到,data字典被转换成了一串二进制的字节流。 ### 反序列化 将字节流转换成Python对象的过程称为反序列化,可以使用loads函数实现: ```python import pickle bytes_data = b'\x80\x04\x95\x17\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x03Tom\x94\x8c\x03age\x94K\x12\x8c\x06gender\x94\x8c\x04male\x94u.' data = pickle.loads(bytes_data) print(data) ``` 输出结果为: ``` {'name': 'Tom', 'age': 18, 'gender': 'male'} ``` ### 文件操作 除了使用dumps和loads函数进行序列化和反序列化操作外,pickle模块还提供了dump和load函数用于将对象序列化到文件或从文件中反序列化对象。 将对象序列化到文件: ```python import pickle data = {'name': 'Tom', 'age': 18, 'gender': 'male'} with open('data.pkl', 'wb') as f: pickle.dump(data, f) ``` 从文件中反序列化对象: ```python import pickle with open('data.pkl', 'rb') as f: data = pickle.load(f) print(data) ``` ## 协议0 协议0是最早的版本,它使用ASCII码来表示序列化后的对象,因此序列化后的数据比较大。使用协议0时,可以指定文件打开模式为't',表示以文本模式打开文件: ```python import pickle data = {'name': 'Tom', 'age': 18, 'gender': 'male'} with open('data.pkl', 'wt') as f: pickle.dump(data, f, protocol=0) with open('data.pkl', 'rt') as f: data = pickle.load(f) print(data) ``` 输出结果为: ``` {'age': 18, 'gender': 'male', 'name': 'Tom'} ``` ## 协议1 协议1和协议2是Python2中引入的,它们使用更紧凑的二进制格式表示序列化后的对象。协议1可以指定文件打开模式为'wb',表示以二进制模式打开文件: ```python import pickle data = {'name': 'Tom', 'age': 18, 'gender': 'male'} with open('data.pkl', 'wb') as f: pickle.dump(data, f, protocol=1) with open('data.pkl', 'rb') as f: data = pickle.load(f) print(data) ``` 输出结果为: ``` {'name': 'Tom', 'age': 18, 'gender': 'male'} ``` ## 协议2 协议2是协议1的改进版本,它支持新的对象类型,如集合、字典等。在Python2中,协议2是默认使用的协议,如果不指定协议号,则使用协议2。 在Python3中,pickle模块默认使用协议3,但仍然可以使用协议2: ```python import pickle data = {'name': 'Tom', 'age': 18, 'gender': 'male'} with open('data.pkl', 'wb') as f: pickle.dump(data, f, protocol=2) with open('data.pkl', 'rb') as f: data = pickle.load(f) print(data) ``` 输出结果为: ``` {'name': 'Tom', 'age': 18, 'gender': 'male'} ``` ## 协议3 协议3是Python3.0中引入的,它支持更多的对象类型,如bytes、bytearray、set等。在Python3中,协议3是默认使用的协议,因此可以省略protocol参数: ```python import pickle data = {'name': 'Tom', 'age': 18, 'gender': 'male'} with open('data.pkl', 'wb') as f: pickle.dump(data, f) with open('data.pkl', 'rb') as f: data = pickle.load(f) print(data) ``` 输出结果为: ``` {'name': 'Tom', 'age': 18, 'gender': 'male'} ``` ## 协议4 协议4是Python3.4中引入的,它支持更多的对象类型,如memoryview、tuple等。协议4还支持从流中读取指定长度的数据,从而避免了一次性读取太多数据导致内存溢出的问题。 使用协议4时,需要将文件打开模式指定为'xb',表示以二进制模式打开文件,并且不能使用文本模式: ```python import pickle data = {'name': 'Tom', 'age': 18, 'gender': 'male'} with open('data.pkl', 'xb') as f: pickle.dump(data, f, protocol=4) with open('data.pkl', 'rb') as f: data = pickle.load(f) print(data) ``` 输出结果为: ``` {'name': 'Tom', 'age': 18, 'gender': 'male'} ``` ## 注意事项 在使用pickle模块时,需要注意以下几点: - 序列化和反序列化的对象必须是可序列化的,即不能包含不能序列化的对象。 - 序列化和反序列化的对象必须是相同的类型,否则可能会出现错误。 - 序列化和反序列化的对象必须是可信的,否则可能会被注入恶意代码。 - 不同协议之间的兼容性不同,不同协议之间的序列化和反序列化操作不一定是互逆的。因此,在使用不同协议时,需要注意协议号的兼容性和相应的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值