python保存dat⽂件_将数据存⼊⽂件
要常常喜乐,不住地祷告,凡事谢恩,因为这是神在基督耶稣⾥向你们所定的旨意。不要消灭圣灵的感动,不要藐视先知的讲论。但要凡事察验,善美的要持守,各样的恶事要禁戒不作。(1 THESSALONIANS 5:16-22)
将数据存⼊⽂件
在《⽂件(1)》和《⽂件(2)》中,已经学习了如何读写⽂件。
如果在程序中,有数据要保存到磁盘中,放到某个⽂件中是⼀种不错的⽅法。但是,如果像以前那样存,未免有点凌乱,并且没有什么良好的存储格式,导致数据以后被读出来的时候遇到⿇烦,特别是不能让另外的使⽤者很好地理解。不要忘记了,编程是⼀个合作的活。还有,存储的数据不⼀定都是类似字符串、整数那种基础类型的。
总⽽⾔之,需要将要存储的对象格式化(或者叫做序列化),才好存好取。这就有点类似集装箱的作⽤。
所以,要⽤到本讲中提供的⽅式。
pickle
pickle是标准库中的⼀个模块,还有跟它完全⼀样的叫做cpickle,两者的区别就是后者更快。所以,下⾯操作中,不管是⽤import pickle,还是⽤import cpickle as pickle,在功能上都是⼀样的。
>>> import pickle
>>> integers = [1, 2, 3, 4, 5]
>>> f = open("22901.dat", "wb")
>>> pickle.dump(integers, f)
>>> f.close()
⽤pickle.dump(integers, f)将数据integers保存到了⽂件22901.dat中。如果你要打开这个⽂件,看⾥⾯的内容,可能有点失望,但是,它对计算机是友好的。这个步骤,可以称之为将对象序列化。⽤到的⽅法是:
pickle.dump(obj,file[,protocol])
obj:序列化对象,上⾯的例⼦中是⼀个列表,它是基本类型,也可以序列化⾃⼰定义的类型。
file:⼀般情况下是要写⼊的⽂件。更⼴泛地可以理解为为拥有write()⽅法的对象,并且能接受字符串为为参数,所以,它还可以是⼀个StringIO对象,或者其它⾃定义满⾜条件的对象。
protocol:可选项。默认为False(或者说0),是以ASCII格式保存对象;如果设置为1或者True,则以压缩的⼆进制格式保存对象。
下⾯换⼀种数据格式,并且做对⽐:
>>> import pickle
>>> d = {}
>>> integers = range(9999)
>>> d["i"] = integers #下⾯将这个dict格式的对象存⼊⽂件
>>> f = open("22902.dat", "wb")
>>> pickle.dump(d, f) #⽂件中以ascii格式保存数据
>>> f.close()
>>> f = open("22903.dat", "wb")
>>> pickle.dump(d, f, True) #⽂件中以⼆进制格式保存数据
>>> f.close()
>>> s1 = os.stat("22902.dat").st_size #得到两个⽂件的⼤⼩
>>> s2 = os.stat("22903.dat").st_size
>>> print "%d, %d, %.2f%%" % (s1, s2, (s2+0.0)/s1*100)
68903, 29774, 43.21%
⽐较结果发现,以⼆进制⽅式保存的⽂件⽐以ascii格式保存的⽂件⼩很多,前者约是后者的43%。
所以,在序列化的时候,特别是⾯对较⼤对象时,建议将dump()的参数True设置上,虽然现在存储设备的价格便宜,但是能省还是省点⽐较好。
存⼊⽂件,仅是⼀个⽬标,还有另外⼀个⽬标,就是要读出来,也称之为反序列化。
>>> integers = pickle.load(open("22901.dat", "rb"))
>>> print integers
[1, 2, 3, 4, 5]
就是前⾯存⼊的那个列表。再看看被以⼆进制存⼊的那个⽂件:
>>> f = open("22903.dat", "rb")
>>> d = pickle.load(f)
>>> print d
{'i': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, .... #省略后⾯的数字}
>>> f.close()
还是有⾃⼰定义数据类型的需要,这种类型是否可以⽤上述⽅式存⼊⽂件并读出来呢?看下⾯的例⼦:
>>> import cPickle as pickle #cPickle更快
>>> import StringIO #标准库中的⼀个模块,跟file功能类似,只不过是在内存中操作“⽂件”
>>> class Book(object): #⾃定义⼀种类型
... def __init__(self,name):
python怎么读取dat文件... self.name = name
... def my_book(self):
... print "my book is: ", self.name
...
>>> pybook = Book("")
>>> _book()
my book is:
>>> file = StringIO.StringIO()
>>> pickle.dump(pybook, file, 1)
>>> value() #查看“⽂件”内容,注意下⾯不是乱码
ccopy_reg
q(c__main__
Book
qc__builtin__
object
qNtRq}qUnameqUsb.
>>> pickle.dump(pybook, file) #换⼀种⽅式,再看内容,可以⽐较⼀下>>> value() #视觉上,两者就有很⼤差异
ccopy_reg
_reconstructor
q(c__main__
Book
qc__builtin__
object
py_reg
_reconstructor
p1
(c__main__
Book
p2
c__builtin__
object
p3
NtRp4
(dp5
S'name'
p6
S''
p7
sb.
如果要从⽂件中读出来:
>>> file.seek(0) #到对应类型
>>> pybook2 = pickle.load(file)
>>> _book()
my book is:
>>> file.close()
shelve
pickle模块已经表现出它⾜够好的⼀⾯了。不过,由于数据的复杂性,pickle只能完成⼀部分⼯作,在另外更复杂的情况下,它就稍显⿇烦了。于是,⼜有了shelve。
shelve模块也是标准库中的。先看⼀下基本操作:写⼊和读取
>>> import shelve
>>> s = shelve.open("22901.db")
>>> s["name"] = "www.itdiffer"
>>> s["lang"] = "python"
>>> s["pages"] = 1000
>>> s["contents"] = {"first":"base knowledge","second":"day day up"}
>>> s.close()
以上完成了数据写⼊的过程。其实,这更接近数据库的样式了。下⾯是读取。
>>> s = shelve.open("22901.db")
>>> name = s["name"]
>>> print name
www.itdiffer
>>> contents = s["contents"]
>>> print contents
{'second': 'day day up', 'first': 'base knowledge'}
当然,也可以⽤for语句来读:
>>> for k in s:
... print k, s[k]
...
contents {'second': 'day day up', 'first': 'base knowledge'}
lang python
pages 1000
name www.itdiffer
不管是写,还是读,都似乎要简化了。所建⽴的对象s,就如同字典⼀样,可称之为类字典对象。所以,可以如同操作字典那样来操作它。
但是,要⼩⼼坑:
>>> f = shelve.open("22901.db")
>>> f["author"]
['qiwsir']
>>> f["author"].append("Hetz") #试图增加⼀个
>>> f["author"] #坑就在这⾥
['qiwsir']
>>> f.close()
当试图修改⼀个已有键的值时,没有报错,但是并没有修改成功。要填平这个坑,需要这样做:>>> f = shelve.open("22901.db", writeback=True) #多⼀个参数True
>>> f["author"].append("Hetz")
>>> f["author"] #没有坑了
['qiwsir', 'Hetz']
>>> f.close()
还⽤for循环⼀下:
>>> f = shelve.open("22901.db")
>>> for k,v in f.items():
... print k,": ",v
...
contents : {'second': 'day day up', 'first': 'base knowledge'}
lang : python
pages : 1000
author : ['qiwsir', 'Hetz']
name : www.itdiffer
shelve更像数据库了。
不过,它还不是真正的数据库。真正的数据库在后⾯。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。