本??容
- 前言
- json模?
- pickle模?
- shelve模?
- ??
一、前言
1. ??需求
每??程?言都有各自的?据?型,其中面向?象的?程?言?允???者自定??据?型(如:自定??),Python也是一?。?多?候我??有??的需求:
- 把?存中的各??据?型的?据通????送?其?机器或客?端;
- 把?存中的各??据?型的?据保存到本地磁?持久化;
2.?据格式
如果要?一?系??的?据通??????其?系?或客?端,我?通常都需要先把?些?据?化?字符串或字?串,而且需要?定一??一的?据格式才能??据接收端正?解析?理解?些?据的含?。
XML
是早期被?泛使用的?据交?格式,在早期的系?集成?文中?常可以看到?的身影;如今大家使用更多的?据交?格式是
JSON(JavaScript Object Notation)
,?是一??量?的?据交?格式。JSON相?于XML而言,更加加?、易于??和??,同?也易于机器解析和生成。除此之外,我?也可以自定??部使用的?据交?格式。
如果是想把?据持久化到本地磁?,?部分?据通常只是供系??部使用,因此?据????以及??后的?据格式也就不要求是?准、?一的,只要本系??部能?正????可。但是,系??部的????通常??着?程?言版本的升?而?生?化(改?算法、提高效率),因此通常?涉及??????程?言的版本兼容??,下面要介?的pickle??就是??一?例子。
3. 序列化/反序列化
??象???可通?????或可以存?到本地磁?的?据格式(如:XML、JSON或特定格式的字?串)的?程??序列化;反之,???反序列化。
4.相?模?
本?要介?的就是Python?置的??用于?行?据序列化的模?:
模?名? | 描述 | 提供的api
- | - | -
json | 用于??Python?据?型?通用(json)字符串之?的?? | dumps()、dump()、loads()、load()
pickle | 用于??Python?据?型?Python特定二?制格式之?的?? | dumps()、dump()、loads()、load()
shelve | ??用于?Python?据?型的?据持久化到磁?,shelve是一??似dict的?象,操作十分便捷 | open()
二、json模?
大部分?程?言都?提供?理json?据的接口,Python 2.6?始加入了json模?,且把?作?一??置模?提供,无需下??可使用。
1. 序列化?反序列化
Python的JSON模? 序列化?反序列化的?程分?叫做:encoding 和 decoding。
- encoding:
把Python?象??成JSON字符串
- decoding:
把JSON字符串??成python?象
json模?提供了以下??方法??行序列化和反序列化操作:
# 序列化:?Python?象??成json字符串
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)
# 反序列化:?json字符串??成Python?象
loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
除此之外,json模??提供了???外的方法允?我?直接?序列化后得到的json?据保存到文件中,以及直接?取文件中的json?据?行反序列化操作:
# 序列化:?Python?象??成json字符串?存?到文件中
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)
# 反序列化:?取指定文件中的json字符串???成Python?象
load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
2. JSON?Python之??据?型???系
Python?JSON
Python | JSON
- | -
dict | Object
list, tuple | array
str | string
int, float, int- & float-derived Enums | numbers
True | true
False | false
None | null
JSON?Python
JSON | Python
- | -
object | dict
array | list
string | str
number(int) | int
number(real) | float
true | True
false | False
null | None
?明:
- Python dict中的非字符串key被??成JSON字符串?都?被???小?字符串;
- Python中的tuple,在序列化??被???array,但是反序列化?,array?被?化?list;
- 由以上?点可知,?Python?象中包含tuple?据或者包含dict,且dict中存在非字符串的key?,反序列化后得到的?果?原?的Python?象是不一致的;
- ?于Python?置的?据?型(如:str, unicode, int, float, bool, None, list, tuple, dict)json模?可以直接?行序列化/反序列化?理;?于自定??的?象?行序列化和反序列化?,需要我?自己定?一?方法?完成定?object和dict之??行?化。
3. ?例:?置?据?型序列化/反序列化
序列化
# 序列化
>>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)})
'{"a": "str", "c": true, "b": 11.1, "e": 10, "d": null, "g": [4, 5, 6], "f": [1, 2, 3]}'
sort_keys??:
表示序列化?是否?dict的key?行排序(dict默?是无序的)
# 序列化??key?行排序
>>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, sort_keys=True)
'{"a": "str", "b": 11.1, "c": true, "d": null, "e": 10, "f": [1, 2, 3], "g": [4, 5, 6]}'
indent??:
表示??的意思,?可以使得?据存?的格式?得更加?雅、可?性更强;如果indent是一?非?整?或字符串,?JSON array元素和object成???被以相?的?????行打印?出;如果indent是0或??或空字符串,??只??入?行,不?有??。
# 序列化??key?行排序及格式化?出
>>> print(json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, sort_keys=True, indent=4))
{
"a": "str",
"b": 11.1,
"c": true,
"d": null,
"e": 10,
"f": [
1,
2,
3
],
"g": [
4,
5,
6
]
}
separators??:
?管indent??可以使得?据存?的格式?得更加?雅、可?性更强,但是那是通?添加一些冗余的空白字符?行?充的。?json被用于???据通信?,???可能的?少无用的?据??,??可以?省???加快?据??速度。json模?序列化Python?象后得到的json字符串中的','?和':'?分隔符后默?都?附加一?空白字符,我?可以通?separators??重新指定分隔符,?而去除无用的空白字符;
- ???的???是一?tuple(item_separator, key_separator)
- 如果indent是None,其默???(', ', ': ')
- 如果indent不?None,?默???(',', ': ')
- 我?可以通??separator???(',', ':')?消除空白字符
>>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)})
'{"a": "str", "c": true, "b": 11.1, "e": 10, "d": null, "g": [4, 5, 6], "f": [1, 2, 3]}'
>>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, separators=(',',':'))
'{"a":"str","c":true,"b":11.1,"e":10,"d":null,"g":[4,5,6],"f":[1,2,3]}'
ensure_ascii??:
????的??True(默??)?,?出中的所有非ASCII字符(比如中文)都?被??成'\uXXXX'?成的序列,得到的?果是一?完全由ASCII字符?成的str?例。如果我?想得到一?人?可?的?出?果,需要把ensure_ascii??的??置?False。
>>> stu={"name": "小明", "age" : 16}
>>> stu_json = json.dumps(stu)
>>> print(stu_json)
'{"name": "\u5c0f\u660e", "age": 16}'
>>> stu_json01 = json.dumps(stu, ensure_ascii=False)
>>> print(stu_json01)
'{"name": "小明", "age": 16}'
?明:
??上'\uXXXX'是Unicode字符??的?存???,??存??名??"unicode-escape",我?可以通?
unicodestr.encode('unicode-escape')
和
decode('unicode-escape')
?完成Unicode字符串?Unicode?存??序列?行相互??,如下所示:
>>> str1 = "hello 中?"
>>> str2 = str1.encode("unicode_escape")
>>> print(str2)
b'hello \\u4e2d\\u56fd'
>>> str3 = str2.decode("unicode_escape")
>>> print(str3)
hello 中?
注意str2是字?串,不是字符串,因此\u前面需要再加一?反斜?做??。我?把str2??成字符串就是我?熟悉的格式了:
>>> str4=str2.decode("utf-8")
>>> print(str4)
hello \u4e2d\u56fd
>>>
反序列化
# 反序列化
>>> json.loads('{"a": "str", "c": true, "b": 11.1, "e": 10, "d": null, "g": [4, 5, 6], "f": [1, 2, 3]}')
{'c': True, 'e': 10, 'a': 'str', 'g': [4, 5, 6], 'd': None, 'f': [1, 2, 3], 'b': 11.1}
>>> json.loads('{"a":"str","c":true,"b":11.1,"e":10,"d":null,"g":[4,5,6],"f":[1,2,3]}')
{'c': True, 'e': 10, 'a': 'str', 'g': [4, 5, 6], 'd': None, 'f': [1, 2, 3], 'b': 11.1}
dump()?load()函?示例
# 序列化到文件中
>>> with open('test.json', 'w') as fp:
... json.dump({'a':'str中?', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, fp, indent=4)
# 反序列化文件中的?容
>>> with open('test.json', 'r') as fp:
... json.load(fp)
{'e': 10, 'g': [4, 5, 6], 'b': 11.1, 'c': True, 'd': None, 'a': 'str中?', 'f': [1, 2, 3]}
需要?明的是:
如果??使用相同的fp重??用dump()函?去序列化多??象(或序列化同一??象多次),???生一?无效的JSON文件,也就是??于一?fp只能?用一次dump()。
4. ?例:自定??据?型的序列化/反序列化
Python是面向?象的?程?言,我?可以自定?需要的?据?型;??工作中,我?常常?用到自定??据?型的序列化?反序列化操作。要??自定??据?型的序列化?反序列化有??方式:
- 通???函???
- 通??承JSONEncoder和JSONDecoder???
首先?自定?一??据?型
class Student(object):
def __init__(self, name, age, sno):
self.name = name
self.age = age
self.sno = sno
def __repr__(self):
return 'Student [name: %s, age: %d, sno: %d]' % (self.name, self.age, self.sno)
直接?用dumps()方法?引?TypeError??:
>>> stu = Student('Tom', 19, 1)
>>> print(stu)
Student [name: Tom, age: 19, sno: 1]
>>>
>>> json.dumps(stu)
...
TypeError: Student [name: Tom, age: 19, sno: 1] is not JSON serializable
上面的?常信息中指出:stu?象不可以被序列化?JSON格式的?据。那?我?分?通?“????函?” 和 “?承JSONEncoder和JSONDecoder?” ??????自定??据?型的JSON序列化和反序列化。
方法1:????函?
那?????函?要完成????据?型之?的????
?上面列出的JSON?Python?据?型的??表中可知,JSON中的object??的是Python中的dict,因此要?Python中的自定??据?型的?象?行序列化,就需要先把???象??成json模?可以直接?行序列化dict?型。由此可知,????函?是要完成的是Python?象(不是JSON?象)?dict之?的相互??,且序列化????程是“Python?象 --> dict --> JSON object”,反序列化的?程是“JSON object -> dict --> Python?象”。所以,我?需要??????函??分???序列化和反序列化?的???程。
def obj2dict(obj):
d = {}
d['__class__'] = obj.__class__.__name__
d['__module__'] = obj.__module__
d.update(obj.__dict__)
return d
def dict2obj(d):
if '__class__' in d:
class_name = d.pop('__class__')
module_name = d.pop('__module__')
module = __import__(module_name)
class_ = getattr(module, class_name)
args = dict((key.encode('ascii'), value) for key, value in d.items())
instance = class_(**args)
else:
instance = d
return instance
序列化??:
>>> import json
>>> obj2dict(stu)
{'sno': 1, '__module__': '__main__', 'age': 19, '__class__': 'Student', 'name': 'Tom'}
>>> json.dumps(obj2dict(stu))
'{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}'
>>> json.dumps(stu, default=obj2dict)
'{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}'
json.dumps(stu, default=obj2dict)
等价于
json.dumps(obj2dict(stu))
反序列化??:
>>> json.loads('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}')
{u'sno': 1, u'__module__': u'__main__', u'age': 19, u'name': u'Tom', u'__class__': u'Student'}
>>> dict2obj(json.loads('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}'))
Student [name: Tom, age: 19, sno: 1]
>>> json.loads('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}', object_hook=dict2obj)
Student [name: Tom, age: 19, sno: 1]
json.loads(JSON_STR, object_hook=dict2obj)
等价于
dict2obj(json.loads(JSON_STR))
方法2:?承JSONEncoder和JSONDecoder??子?
import json
class MyJSONEncoder(json.JSONEncoder):
def default(self, obj):
d = {}
d['__class__'] = obj.__class__.__name__
d['__module__'] = obj.__module__
d.update(obj.__dict__)
return d
class MyJSONDecoder(json.JSONDecoder):
def __init__(self):
json.JSONDecoder.__init__(self, object_hook=self.dict2obj)
def dict2obj(self, d):
if '__class__' in d:
class_name = d.pop('__class__')
module_name = d.pop('__module__')
module = __import__(module_name)
class_ = getattr(module, class_name)
args = dict((key.encode('ascii'), value) for key, value in d.items())
instance = class_(**args)
else:
instance = d
return instance
序列化??:
>>> stu = Student('Tom', 19, 1)
# 方式一:直接?用子?MyJSONEncoder的encode()方法?行序列化
>>> MyJSONEncoder().encode(stu)
'{"__class__": "Student", "__module__": "__main__", "name": "Tom", "age": 19, "sno": 1}'
>>> MyJSONEncoder(separators=(',', ':')).encode(stu)
'{"__class__":"Student","__module__":"__main__","name":"Tom","age":19,"sno":1}'
# 方式二:?子?MyJSONEncoder作?cls??的????json.dumps()函?
>>> json.dumps(stu, cls=MyJSONEncoder)
'{"__class__": "Student", "__module__": "__main__", "name": "Tom", "age": 19, "sno": 1}'
>>> json.dumps(stu, cls=MyJSONEncoder, separators=(',', ':'))
'{"__class__":"Student","__module__":"__main__","name":"Tom","age":19,"sno":1}'
反序列化??:
>>> MyJSONDecoder().decode('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}')
Student [name: Tom, age: 19, sno: 1]
?明:
??????
MyJSONDecoder().decode(JSON_STR)
和
json.loads(JSON_STR, object_hook=dict2obj)
只能在Python 2.7上正??行,在Python 3.5上无法正??行;而
json.loads(JSON_STR, cls=MyJSONDecoder)
无?在Python 2.7?是在Python 3.5上都无法正??行。??明json模??于自定??据?型的反序列化支持?是比?有限的,但是我?也可以通?json.loads(JSON_STR)函?,不指定cls???得到一?dict?象,然后自己完成dict到object的??。
?承JSONEncoder??序列化??有一??外的作用,就是可以通?iterencode()方法把一??大的?据?象分多次?行序列化,??于????、磁?持久化等情景非常有用。
>>> for chunk in MyJSONEncoder().iterencode(stu):
... print(chunk)
...
{
"__class__"
:
"Student"
,
"name"
:
"Tom"
,
"__module__"
:
"__main__"
,
"sno"
:
1
,
"age"
:
19
}
大?据?象序列化?????代?:
for chunk in JSONEncoder().iterencode(bigobject):
mysocket.write(chunk)
三、pickle模?
pickle模???了用于?Python?象???行 序列化 和 反序列化 的二?制??,?json模?不同的是pickle模?序列化和反序列化的?程分?叫做 pickling 和 unpickling:
- pickling:
是?Python?象???字?流的?程;
- unpickling:
是?字?流二?制文件或字??象??回Python?象的?程;
1. pickle模??json模??比
- JSON是一?文本序列化格式(??出的是unicode文件,大多??候?被???utf-8),而pickle是一?二?制序列化格式;
- JOSN是我?可以??的?据格式,而pickle是二?制格式,我?无法??;
- JSON是?特定的?程?言或系?无?的,且?在Python生?系?之外被?泛使用,而pickle使用的?据格式是特定于Python的;
- 默?情?下,JSON只能表示Python?建?据?型,?于自定??据?型需要一些?外的工作?完成;pickle可以直接表示大量的Python?据?型,包括自定?据?型(其中,?多是通?巧妙地使用Python?省功能自???的;??的情?可以通???specific object API?解?)
2. pickle模?使用的?据流格式
上面提到,pickle使用的?据格式是特定于Python的。?使得?不受?如JSON或XDR的外部?准限?,但是?也意味着非Python程序可能无法重建pickled Python?象。默?情?下,pickle?据格式使用相???的二?制表示。如果需要最佳大小特征,可以有效的??pickled?据。pickletools模?包含可以用于?pickle生成的?据流?行分析的工具。目前有5?不同的??可以用于pickle。使用的??越高,就需要更新的Python版本去?取pickle?生的?据:
- ??v0是原始的“人?可?”??,?且向后兼容早期的Python版本;
- ??v1是一??的二?制格式,也?早期版本的Python兼容;
- ??v2在Python 2.3中引入,?提供更高效的pickling;
- ??v3是在Python 3.0添加的??,?明?支持bytes?象,且不能被Python 2.x ?行unpickle操作;?是默???,也是?需要兼容其他Python 3版本?被推?使用的??;
- ??4是在Python 3.4添加的??,?添加了??大?象的支持,pickling更多??的?象,以及一些?据格式的?化。
?明:
Python 2.x中默?使用的是??v0,如果??指定???或HIGHEST_PROTOCOL,?使用?前可用的最高??版本;Python 3.x中默?使用的是??v3,?兼容其他Python 3版本,但是不兼容Python 2。
注意:
序列化(Serialization)是一?比持久化(Persistence)更加原始的?念;?然
pickle
可以??文件?象,但是?不?理持久化?象的命名??,也不?理?持久化?象的??????(甚至更??的??)。
pickle
模?可以????象???字?流,?且可以?字?流???具有相同?部??的?象。或?最可能??些字?流做的事情是????入文件,但是也可以????行????或???存?在?据?中。
shelve
模?提供了一???的接口用于在DBM?格的?据?文件上??象?行pickle和unpickle操作。
3. pickle模?提供的相?函?
pickle模?提供的??序列化/反序列化的函??json模?基本一致:
# ?指定的Python?象通?pickle序列化作?bytes?象返回,而不是?其?入文件
dumps(obj, protocol=None, *, fix_imports=True)
# ?通?pickle序列化后得到的字??象?行反序列化,???Python?象?返回
loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")
# ?指定的Python?象通?pickle序列化后?入打?的文件?象中,等价于`Pickler(file, protocol).dump(obj)`
dump(obj, file, protocol=None, *, fix_imports=True)
# ?打?的文件?象中?取pickled?象表?形式?返回通?pickle反序列化后得到的Python?象
load(file, *, fix_imports=True, encoding="ASCII", errors="strict")
?明:
上面???方法??中,*?后面的??都是Python 3.x新增的,目的是?了兼容Python 2.x,具?用法??看官方文?。
4. ?例:?置?据?型的序列化/反序列化
Python 2.x
>>> import pickle
>>>
>>> var_a = {'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}
# 序列化
>>> var_b = pickle.dumps(var_a)
>>> var_b
"(dp0\nS'a'\np1\nS'str'\np2\nsS'c'\np3\nI01\nsS'b'\np4\nF11.1\nsS'e'\np5\nI10\nsS'd'\np6\nNsS'g'\np7\n(I4\nI5\nI6\ntp8\nsS'f'\np9\n(lp10\nI1\naI2\naI3\nas."
# 反序列化
>>> var_c = pickle.loads(var_b)
>>> var_c
{'a': 'str', 'c': True, 'b': 11.1, 'e': 10, 'd': None, 'g': (4, 5, 6), 'f': [1, 2, 3]}
Python 3.x
>>> import pickle
>>>
>>> var_a = {'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}
# 序列化
>>> var_b = pickle.dumps(var_a)
>>> var_b
b'\x80\x03}q\x00(X\x01\x00\x00\x00eq\x01K\nX\x01\x00\x00\x00aq\x02X\x03\x00\x00\x00strq\x03X\x01\x00\x00\x00fq\x04]q\x05(K\x01K\x02K\x03eX\x01\x00\x00\x00gq\x06K\x04K\x05K\x06\x87q\x07X\x01\x00\x00\x00bq\x08G@&333333X\x01\x00\x00\x00cq\t\x88X\x01\x00\x00\x00dq\nNu.'
# 反序列化
>>> var_c = pickle.loads(var_b)
>>> var_c
{'e': 10, 'a': 'str', 'f': [1, 2, 3], 'g': (4, 5, 6), 'b': 11.1, 'c': True, 'd': None}
dump()?load()
>>> import pickle
>>>
>>> var_a = {'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}
# 持久化到文件
>>> with open('pickle.txt', 'wb') as f:
... pickle.dump(var_a, f)
...
# ?文件中?取?据
>>> with open('pickle.txt', 'rb') as f:
... var_b = pickle.load(f)
...
>>> var_b
{'e': 10, 'a': 'str', 'f': [1, 2, 3], 'g': (4, 5, 6), 'b': 11.1, 'c': True, 'd': None}
>>>
?明:
- 默?情?下Python 2.x中pickled后的?据是字符串形式,需要?????字??象才能被Python 3.x中的pickle.loads()反序列化;Python 3.x中pickling所使用的??是v3,因此需要在?用pickle.dumps()?指定可???protocol?Python 2.x所支持的??版本(0,1,2),否?pickled后的?据不能被被Python 2.x中的pickle.loads()反序列化;
- Python 3.x中pickle.dump()和pickle.load()方法中指定的文件?象,必?以二?制模式打?,而Python 2.x中可以以二?制模式打?,也可以以文本模式打?。
5. ?例:自定??据?型的序列化/反序列化
首先?自定?一??据?型:
class Student(object):
def __init__(self, name, age, sno):
self.name = name
self.age = age
self.sno = sno
def __repr__(self):
return 'Student [name: %s, age: %d, sno: %d]' % (self.name, self.age, self.sno)
pickle模?可以直接?自定?据?型?行序列化/反序列化操作,无需???外的?理函?或?。
>>> stu = Student('Tom', 19, 1)
>>> print(stu)
Student [name: Tom, age: 19, sno: 1]
# 序列化
>>> var_b = pickle.dumps(stu)
>>> var_b
b'\x80\x03c__main__\nStudent\nq\x00)\x81q\x01}q\x02(X\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Tomq\x04X\x03\x00\x00\x00ageq\x05K\x13X\x03\x00\x00\x00snoq\x06K\x01ub.'
# 反序列化
>>> var_c = pickle.loads(var_b)
>>> var_c
Student [name: Tom, age: 19, sno: 1]
# 持久化到文件
>>> with open('pickle.txt', 'wb') as f:
... pickle.dump(stu, f)
...
# ?文件??取?据
>>> with open('pickle.txt', 'rb') as f:
... pickle.load(f)
...
Student [name: Tom, age: 19, sno: 1]
四、shelve模?
shelve是一???的?据存?方案,?似key-value?据?,可以?方便的保存python?象,其?部是通?pickle??????据序列化。shelve只有一?open()函?,??函?用于打?指定的文件(一?持久的字典),然后返回一?shelf?象。shelf是一?持久的、?似字典的?象。??“dbm”的不同之?在于,其values?可以是任意基本Python?象--pickle模?可以?理的任何?据。?包括大多???例、???据?型和包含?多共享子?象的?象。keys?是普通的字符串。
open(filename, flag='c', protocol=None, writeback=False)
flag
??表示打??据存?文件的格式,可取??
dbm.open()
函?一致:
?
|
描述
|
'r'
|
以只?模式打?一?已?存在的?据存?文件
|
'w'
|
以??模式打?一?已?存在的?据存?文件
|
'c'
|
以??模式打?一??据存?文件,如果不存在??建
|
'n'
|
?是?建一?新的、空?据存?文件,?以??模式打?
|
protocol
??表示序列化?据所使用的??版本,默?是pickle v3;
writeback
??表示是否??回?功能。
我?可以把shelf?象?dict?使用--存?、更改、??某?key??的?据,?操作完成之后,?用shelf?象的close()函??可。?然,也可以使用上下文管理器(with?句),避免每次都要手??用close()方法。
?例:?置?据?型操作
# 保存?据
with shelve.open('student') as db:
db['name'] = 'Tom'
db['age'] = 19
db['hobby'] = ['?球', '看?影', '?吉他']
db['other_info'] = {'sno': 1, 'addr': 'xxxx'}
# ?取?据
with shelve.open('student') as db:
for key,value in db.items():
print(key, ': ', value)
?出?果:
name : Tom
age : 19
hobby : ['?球', '看?影', '?吉他']
other_info : {'sno': 1, 'addr': 'xxxx'}
?例:自定??据?型操作
# 自定?class
class Student(object):
def __init__(self, name, age, sno):
self.name = name
self.age = age
self.sno = sno
def __repr__(self):
return 'Student [name: %s, age: %d, sno: %d]' % (self.name, self.age, self.sno)
# 保存?据
tom = Student('Tom', 19, 1)
jerry = Student('Jerry', 17, 2)
with shelve.open("stu.db") as db:
db['Tom'] = tom
db['Jerry'] = jerry
# ?取?据
with shelve.open("stu.db") as db:
print(db['Tom'])
print(db['Jerry'])
?出?果:
Student [name: Tom, age: 19, sno: 1]
Student [name: Jerry, age: 17, sno: 2]
五、??
1. ?比
json模?常用于??web接口,?Python?据???通用的json格式???其?系?或客?端;也可以用于?Python?据保存到本地文件中,缺点是明文保存,保密性差。?外,如果需要保存非?置?据?型需要???外的??函?或自定??。
pickle模?和shelve模?由于使用其特有的序列化??,其序列化之后的?据只能被Python??,因此只能用于Python系??部。?外,Python 2.x 和 Python
3.x 默?使用的序列化??也不同,如果需要互相兼容需要在序列化?通?protocol??指定??版本。除了上面?些缺点外,pickle模?和shelve模?相?于json模?的?点在于?于自定??据?型可以直接序列化和反序列化,不需要???外的??函?或?。
shelve模?可以看做是pickle模?的升?版,因?shelve使用的就是pickle的序列化??,但是shelve比pickle提供的操作方式更加??、方便。shelve模?相?于其???模?在?Python?据持久化到本地磁??有一??明?的?点就是,?允?我?可以像操作dict一?操作被序列化的?据,而不必一次性的保存或?取所有?据。
2. 建?
- 需要?外部系?交互?用json模?;
- 需要?少量、??Python?据持久化到本地磁?文件?可以考?用pickle模?;
- 需要?大量Python?据持久化到本地磁?文件或需要一些??的?似?据?的增?改?功能?,可以考?用shelve模?。
3. 附?
要??的功能
|
可以使用的api
|
?Python?据?型???(json)字符串
|
json.dumps()
|
?json字符串???Python?据?型
|
json.loads()
|
?Python?据?型以json形式保存到本地磁?
|
json.dump()
|
?本地磁?文件中的json?据???Python?据?型
|
json.load()
|
?Python?据?型???Python特定的二?制格式
|
pickle.dumps()
|
?Python特定的的二?制格式?据???Python?据?型
|
pickle.loads()
|
?Python?据?型以Python特定的二?制格式保存到本地磁?
|
pickle.dump()
|
?本地磁?文件中的Python特定的二?制格式?据???Python?据?型
|
pickle.load()
|
以?型dict的形式?Python?据?型保存到本地磁?或?取本地磁??据?????据?型
|
shelve.open()
|
??交流群:666948590