4
4
5
5
在[ 《文件(1)》] ( ./126.md ) 和[ 《文件(2)》] ( ./127.md ) 中,已经学习了如何读写文件。
6
6
7
- 如果在程序中,有数据要保存到磁盘中,放到某个文件中是一种不错的方法 。但是,如果像以前那样存,未免有点凌乱,并且没有什么良好的存储格式,导致数据以后被读出来的时候遇到麻烦,特别是不能让另外的使用者很好地理解。不要忘记了,编程是一个合作的活。还有,存储的数据不一定都是类似字符串、整数那种基础类型的 。
7
+ 程序执行结果,就是产生一些数据,一般情况下,这些数据数据要保存到磁盘中,最简单的方法就是写入到某个文件 。但是,如果仅仅是简单地把数据写入文件,不是最佳的存储机构。为此,就有了诸多不同的数据存储方式,这些方式不仅能够保证数据被存储,还能够让数据便于读取,此外,还有很多其它方面的优势 。
8
8
9
- 总而言之,需要将要存储的对象格式化(或者叫做序列化),才好存好取。这就有点类似集装箱的作用。
10
-
11
- 所以,要用到本讲中提供的方式。
9
+ 简而言之,就是要将存储的对象格式化(或者叫做序列化),才好存好取。这就有点类似集装箱的作用。
12
10
13
11
##pickle
14
12
15
- pickle是标准库中的一个模块,还有跟它完全一样的叫做cpickle,两者的区别就是后者更快。所以,下面操作中,不管是用` import pickle ` ,还是用` import cpickle as pickle ` ,在功能上都是一样的。
13
+ pickle是标准库中的一个模块,在Python 2中还有一个cpickle,两者的区别就是后者更快。所以,下面操作中,不管是用` import pickle ` ,还是用` import cpickle as pickle ` ,在功能上都是一样的。
14
+
15
+ 而在Python 3中,你只需要` import pickle ` 即可,因为它已经在Python 3中具备了Python 2中的cpickle同样的性能。
16
16
17
17
>>> import pickle
18
18
>>> integers = [1, 2, 3, 4, 5]
19
19
>>> f = open("22901.dat", "wb")
20
20
>>> pickle.dump(integers, f)
21
21
>>> f.close()
22
22
23
- 用` pickle.dump(integers, f) ` 将数据integers保存到了文件22901.dat中。如果你要打开这个文件,看里面的内容,可能有点失望,但是,它对计算机是友好的。这个步骤,可以称之为将对象序列化 。用到的方法是:
23
+ 用` pickle.dump(integers, f) ` 将数据integers保存到了文件22901.dat中。如果你要打开这个文件,看里面的内容,可能有点失望,但是,它对计算机是友好的。这个步骤可以称之为将对象序列化 。用到的方法是:` pickle.dump(obj,file[,protocol]) `
24
24
25
- ` pickle.dump(obj,file[,protocol]) `
26
-
27
- - obj:序列化对象,上面的例子中是一个列表,它是基本类型,也可以序列化自己定义的类型。
28
- - file:一般情况下是要写入的文件。更广泛地可以理解为为拥有write()方法的对象,并且能接受字符串为为参数,所以,它还可以是一个StringIO对象,或者其它自定义满足条件的对象。
25
+ - obj:序列化对象,在上面的例子中是一个列表,它是基本类型,也可以序列化自己定义的对象。
26
+ - file:要写入的文件。可以更广泛地可以理解为为拥有` write() ` 方法的对象,并且能接受字符串为为参数,所以,它还可以是一个` StringIO ` 对象,或者其它自定义满足条件的对象。
29
27
- protocol:可选项。默认为False(或者说0),是以ASCII格式保存对象;如果设置为1或者True,则以压缩的二进制格式保存对象。
30
28
31
- 下面换一种数据格式 ,并且做对比:
29
+ 换一种数据格式 ,并且做对比:
32
30
33
31
>>> import pickle
34
32
>>> d = {}
35
33
>>> integers = range(9999)
36
- >>> d["i"] = integers #下面将这个dict格式的对象存入文件
34
+ >>> d["i"] = integers #下面将这个字典类型的对象存入文件
37
35
38
36
>>> f = open("22902.dat", "wb")
39
37
>>> pickle.dump(d, f) #文件中以ascii格式保存数据
@@ -47,37 +45,37 @@ pickle是标准库中的一个模块,还有跟它完全一样的叫做cpickle
47
45
>>> s1 = os.stat("22902.dat").st_size #得到两个文件的大小
48
46
>>> s2 = os.stat("22903.dat").st_size
49
47
50
- >>> print "%d, %d, %.2f%%" % (s1, s2, (s2+0.0)/s1*100)
48
+ >>> print "%d, %d, %.2f%%" % (s1, s2, (s2+0.0)/s1*100) #Python 3: print("{0:d}, {1:d}, {2:.2f}".format (s1, s2, (s2+0.0)/s1*100))
51
49
68903, 29774, 43.21%
52
50
53
51
比较结果发现,以二进制方式保存的文件比以ascii格式保存的文件小很多,前者约是后者的43%。
54
52
55
- 所以,在序列化的时候,特别是面对较大对象时,建议将dump() 的参数True设置上,虽然现在存储设备的价格便宜,但是能省还是省点比较好。
53
+ 所以,在序列化的时候,特别是面对较大对象时,建议将 ` dump() ` 的参数True设置上,虽然现在存储设备的价格便宜,但是能省还是省点比较好。
56
54
57
- 存入文件,仅是一个目标 ,还有另外一个目标,就是要读出来,也称之为反序列化。
55
+ 将数据保存入文件 ,还有另外一个目标,就是要读出来,也称之为反序列化。
58
56
59
57
>>> integers = pickle.load(open("22901.dat", "rb"))
60
- >>> print integers
58
+ >>> print integers #Python 3: print(integers)
61
59
[1, 2, 3, 4, 5]
62
60
63
- 就是前面存入的那个列表。再看看被以二进制存入的那个文件 :
61
+ 再看看以二进制存入的那个文件 :
64
62
65
63
>>> f = open("22903.dat", "rb")
66
64
>>> d = pickle.load(f)
67
65
>>> print d
68
66
{'i': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, .... #省略后面的数字}
69
67
>>> f.close()
70
68
71
- 还是有自己定义数据类型的需要,这种类型是否可以用上述方式存入文件并读出来呢 ?看下面的例子:
69
+ 如果是自己定义的对象,是否可以用上述方式存入文件并读出来呢 ?看下面的例子:
72
70
73
- >>> import cPickle as pickle #cPickle更快
71
+ >>> import cPickle as pickle #这是Python 2的引入方式,如果是Python 3,直接使用import pickle
74
72
>>> import StringIO #标准库中的一个模块,跟file功能类似,只不过是在内存中操作“文件”
75
73
76
74
>>> class Book(object): #自定义一种类型
77
75
... def __init__(self,name):
78
76
... self.name = name
79
77
... def my_book(self):
80
- ... print "my book is: ", self.name
78
+ ... print "my book is: ", self.name #Python 3: print("my book is: ", self.name)
81
79
...
82
80
83
81
>>> pybook = Book("<from beginner to master>")
@@ -130,9 +128,9 @@ pickle是标准库中的一个模块,还有跟它完全一样的叫做cpickle
130
128
131
129
##shelve
132
130
133
- pickle模块已经表现出它足够好的一面了 。不过,由于数据的复杂性,pickle只能完成一部分工作 ,在另外更复杂的情况下,它就稍显麻烦了。于是,又有了shelve 。
131
+ ` pickle ` 模块已经表现出它足够好的一面了 。不过,由于数据的复杂性,` pickle ` 只能完成一部分工作 ,在另外更复杂的情况下,它就稍显麻烦了。于是,又有了 ` shelve ` 。
134
132
135
- shelve模块也是标准库中的。先看一下基本操作:写入和读取
133
+ ` shelve ` 模块也是标准库中的。先看一下基本写、读操作。
136
134
137
135
>>> import shelve
138
136
>>> s = shelve.open("22901.db")
@@ -142,17 +140,17 @@ shelve模块也是标准库中的。先看一下基本操作:写入和读取
142
140
>>> s["contents"] = {"first":"base knowledge","second":"day day up"}
143
141
>>> s.close()
144
142
145
- 以上完成了数据写入的过程。 其实,这更接近数据库的样式了。下面是读取 。
143
+ 以上完成了数据写入的过程, 其实,这很接近数据库的样式了。下面是读 。
146
144
147
145
>>> s = shelve.open("22901.db")
148
146
>>> name = s["name"]
149
- >>> print name
147
+ >>> print name #Python 3: print(name)
150
148
www.itdiffer.com
151
149
>>> contents = s["contents"]
152
- >>> print contents
150
+ >>> print contents #Python 3: print(contents)
153
151
{'second': 'day day up', 'first': 'base knowledge'}
154
152
155
- 当然,也可以用for语句来读:
153
+ 看到输出的内容,你一定想到,肯定可以用 ` for ` 语句来读,想到了就用代码来测试,这就是Python交互模式的便利之处。
156
154
157
155
>>> for k in s:
158
156
... print k, s[k]
@@ -162,7 +160,7 @@ shelve模块也是标准库中的。先看一下基本操作:写入和读取
162
160
pages 1000
163
161
name www.itdiffer.com
164
162
165
- 不管是写,还是读, 都似乎要简化了。所建立的对象s ,就如同字典一样,可称之为类字典对象。所以,可以如同操作字典那样来操作它。
163
+ 不管是写还是读, 都似乎要简化了。所建立的对象被变量 ` s ` 所引用 ,就如同字典一样,可称之为类字典对象。所以,可以如同操作字典那样来操作它。
166
164
167
165
但是,要小心坑:
168
166
@@ -174,29 +172,27 @@ shelve模块也是标准库中的。先看一下基本操作:写入和读取
174
172
['qiwsir']
175
173
>>> f.close()
176
174
177
- 当试图修改一个已有键的值时,没有报错 ,但是并没有修改成功。要填平这个坑,需要这样做:
175
+ 当试图修改一个已有键的值时没有报错 ,但是并没有修改成功。要填平这个坑,需要这样做:
178
176
179
177
>>> f = shelve.open("22901.db", writeback=True) #多一个参数True
180
178
>>> f[ "author"] .append("Hetz")
181
179
>>> f[ "author"] #没有坑了
182
180
[ 'qiwsir', 'Hetz']
183
181
>>> f.close()
184
182
185
- 还用for循环一下 :
183
+ 还用 ` for ` 循环一下 :
186
184
187
185
>>> f = shelve.open("22901.db")
188
186
>>> for k,v in f.items():
189
- ... print k,": ",v
187
+ ... print k,": ",v #Python 3: print(k,": ",v)
190
188
...
191
189
contents : {'second': 'day day up', 'first': 'base knowledge'}
192
190
lang : python
193
191
pages : 1000
194
192
author : ['qiwsir', 'Hetz']
195
193
name : www.itdiffer.com
196
194
197
- shelve更像数据库了。
198
-
199
- 不过,它还不是真正的数据库。真正的数据库在后面。
195
+ ` shelve ` 更像数据库了。不过,它还不是真正的数据库。真正的数据库在后面。
200
196
201
197
------
202
198
0 commit comments