返回首页 Python 学习笔记

第一部分 Python 语言

第二部分 标准库

数据存储

serialization

marshal

Python 专用的序列化算法,PyCodeObject 就是用该算法序列化后保存到 pyc 二进制文件。与具体的机器架构无关,但可能随 Python 版本发生变化。通常不建议用来存储自定义数据。

支持:None, bool, int, long, float, complex, str, unicode, tuple, list, set, frozenset, dict,code objects, StopIteration。容器元素必须是所支持类型,不能是递归引用。

>>> from marshal import dump, load, dumps, loads

>>> s = dumps(range(10))
>>> s
'[\n\x00\x00\x00i\x00\...\x00\x00'

>>> loads(s)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

保存序列化结果到文件。

>>> with file("test.dat", "w") as f:
...     dump(range(10), f)

>>> with file("test.dat", "r") as f:
...     print load(f)

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

pickle

应该用 cPickle 代替 pickle,按官方文档的说法有千倍的提升,且可相互替换。支持用户自定义类型,支持三种协议版本:

  • 0: 使用可显示的 ASCII 字符编码,便于阅读和手工编辑。(默认)
  • 1: 兼容早期 Python 版本的二进制格式。
  • 2: 最有效的二进制编码格式。
>>> import pickle, cPickle

>>> s = "Hello, World"
>>> d = cPickle.dumps(s, 2)
>>> d
'\x80\x02U\rHello, Worldq\x01.'

>>> cPickle.loads(d)
'Hello, World'

>>> pickle.loads(d)   # 和 pickle 格式完全相同。
'Hello, World'

同样有读写文件的 dump、load 函数。看看支持的数据类型:

  • None, True, False
  • int, long, float, complex
  • str, unicode
  • tuple, list, set, and dict (元素必须是支持类型)
  • function (模块级别的函数)
  • classe (模块级别的自定义类,非嵌套)
  • instance (有 dict 属性,或者实现 pickle protocol 协议)

看看对自定义类型的测试。

>>> class Data(object):
...     def __init__(self, x, y):
...         print "__init__"
...         self._x = x
...         self._y = y

>>> d = Data(100, 200)
__init__

>>> s = cPickle.dumps(d, 2)

>>> d2 = cPickle.loads(s)  # 反序列化并没有调用 __init__
>>> d2.__dict__
{'_x': 100, '_y': 200}

利用 pickle protocol 可以控制序列化的细节。比如下面例子中,我们不像保留 _y 字段。

>>> class Data(object):
...     def __init__(self, x, y):
...         self._x = x
...         self._y = y
...
...     def __getstate__(self):
...         d = self.__dict__.copy()
...         del d["_y"]
...     return d
...
...     def __setstate__(self, state):
...         self.__dict__.update(state)

>>> d = Data(10, 20)

>>> s = cPickle.dumps(d, 2)

>>> d2 = cPickle.loads(s)
>>> d2.__dict__
{'_x': 10}

shevle

将对象 pickle 序列化,然后保存到 anydbm 格式文件。anydbm 是个 KV 结构的数据库,可以保存多个序列化的对象。当然也可以选择使用 dbm、gdbm、bdb。

  • flag: r 读, w 写, c 读写, n 新建、读写。
  • protocol: pickle 版本。
  • writeback: 允许将变更的对象同步到数据库。(还是显式修改保存比较好)
>>> import shelve
>>> from contextlib import closing

>>> with closing(shelve.open("test", protocol = 2)) as f:
... f["a"] = dict(name = "Tom", age = 34, sex = "male")
... f["b"] = (1, ["a", 3], "abcdefg")

>>> !xxd -g 1 -l 100 test.db
0000000: 00 06 15 61 00 00 00 02 00 00 04 d2 00 00 10 00 ...a............
0000010: 00 00 00 0c 00 00 01 00 00 00 01 00 00 00 00 08 ................
0000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0000060: 00 00 00 00 ....

>>> with closing(shelve.open("test", protocol = 2)) as f:
...     print f["a"]
...     print f["b"]
...     print ["c"]

{'age': 34, 'name': 'Tom', 'sex': 'male'}
(1, ['a', 3], 'abcdefg')
['c']
上一篇: 文件与目录 下一篇: 操作系统