数据持久化,就是把数据从内存刷到磁盘上。可是要保证在读取的时候还能恢复到原来的状态。像pickle和json之类的持久化模块基本上无需介绍了,这里介绍两个其余不多用可是功能很强大的模块。
''' 在一些小型程序中,不须要关系型数据库时,能够方便的用持久字典来存储键值对,和python中的字典很是相似。并且dbm的键和值都必须是str或者bytes类型 ''' import dbm ''' 这里第一个参数直接传入文件名,第二个参数表示模式 常见的模式: r:可读,默认就是这个模式 w:可读可写 可是r、w,都必须确保文件已经存在,不然报错。 c:可读可写,文件不存在时会建立 n:可读可写,但老是会建立一个新的文件,也就是说若是建立同名文件,那么以前的内容都会被清空,也就是起不到追加的效果。 所以咱们日常的模式通常都会选择c 第三个参数是权限,这个在windows下基本不用,是一组用八进制表示的数字,默认是0o666,都是可读可写不可执行 ''' db = dbm.open("store", "c") # 打开文件以后,就能够存储值了 # 注意key和value都必须是str或者bytes类型 db["name"] = "satori" db["age"] = "16" db["gender"] = "f" db["anime"] = "东方地灵殿" # 关闭文件,将内容写到磁盘上 db.close() ################################################################ # 打开文件 db = dbm.open("store", "c") print(db.keys()) # [b'name', b'age', b'gender', b'anime'] for key in db.keys(): print(f"key={key}, value={db[key]}") ''' key=b'name', value=b'satori' key=b'age', value=b'16' key=b'gender', value=b'f' key=b'anime', value=b'\xe4\xb8\x9c\xe6\x96\xb9\xe5\x9c\xb0\xe7\x81\xb5\xe6\xae\xbf' '''
会多出来这三个文件
python
''' shelve和dbm比较相似,可是功能远比dbm强大,由于它能够持久化任意对象 ''' import shelve # 参数flag默认是c,所以咱们只须要传入文件名就能够了,这个是自动追加在后面的 # 也就是说我写完以后,再次打开继续写的话,只会追加不会清空 sh = shelve.open("shelve") sh["dict"] = {"name": "satori", "age": 16} sh["list"] = [1, 2, 3, 4] sh["set"] = {1, 2, 3, 2} # 写完以后关闭文件,刷到内存里面 # 关闭以后就没法操做了 sh.close() # 下面咱们就能够操做数据了,下面的代码即使写在另外一个py文件里面也是能够的 sh2 = shelve.open("shelve") print(sh2["dict"], sh2["dict"].keys()) # {'name': 'satori', 'age': 16} dict_keys(['name', 'age']) print(sh2["list"], sum(sh2["list"])) # [1, 2, 3, 4] 10 print(sh2["set"]) # {1, 2, 3} sh2.close() # 能够看到,拿出来的就是原生的对象,能够直接用来进行操做的。那咱们看看本身定义的类可不能够呢? sh3 = shelve.open("shelve") class A: def __init__(self, name, age): self.name = name self.age = age @property def print_info(self): return f"my name is {self.name}, age is {self.age}" a = A("satori", 16) # 将这个类和类的一个实例对象存储进去 sh3["A"] = A sh3["a"] = a sh3.close() ###################################### sh4 = shelve.open("shelve") # sh4["A"]拿到A这个类,传入参数,调用方法 print(sh4["A"]("mashiro", "17").print_info) # my name is mashiro, age is 17 # sh4["a"]拿到a这个实例对象,直接调用方法 print(sh4["a"].print_info) # my name is satori, age is 16 # 咱们发现依旧是能够的,说明了shelve这个模块真的很强大
# 咱们再来看一个例子 import shelve sh = shelve.open("shelve") sh["list"] = [1, 2, 3] sh["str"] = "mashiro" sh.close() ############################## sh = shelve.open("shelve") sh["list"].append("xxxx") sh["str"] = "satori" sh.close() ####################### sh = shelve.open("shelve") print(sh["list"]) # [1, 2, 3] print(sh["str"]) # satori ''' 分析结果,第一次打开文件咱们建立两个键值对 sh["list"] = [1, 2, 3] sh["str"] = "mashiro" 第二次打开文件,修改了两个键的值 第三次打开文件,打印。可是咱们发现sh["str"]改变了,可是sh["list"]没有改变,这是为何? 首先sh["str"] = "satori"很好理解,可是为何sh["list"]没有变? 由于=,咱们是直接赋值,将这一块内存里面的值给换掉,而sh["list"]咱们是作append操做,这只是在原来的基础上进行修改 shelve默认状况下是不会记录,持久化对象的修改的,除非你是建立新的对象,或者是把原来的对象给换掉 若是是在原来的基础上(可变类型),好比列表、字典,进行添加或者删除操做,这些是不会被记录的 因此:sh["list"]=[1, 2, 3] sh["list"].append("xxxx") --->sh["list"]还是[1, 2, 3]不会是[1, 2, 3, "xxx"] 由于shelve没有记录对象自身的修改,若是我想获得指望的结果,一种方法是把对象总体换掉 sh["list"] = [1, 2, 3, "xxxx"],这样等因而从新赋值,是可行的。可是有时候咱们不知道列表里面内容,或者列表里面的内容是一些函数、类什么的、很差写的话,该咋办呢? 其实咱们在打开文件的时候,还能够加上一个参数,叫作writeback '''
import shelve sh = shelve.open("shelve") sh["list"] = [1, 2, 3] sh["str"] = "mashiro" sh.close() ############################## # 若是咱们须要进行修改,那么加上一个writeback=True就能够了,从名字也能看出来 # 这是会将修改的内容重新写回去 sh = shelve.open("shelve", writeback=True) sh["list"].append("xxxx") sh["str"] = "satori" sh.close() ####################### sh = shelve.open("shelve") print(sh["list"]) # [1, 2, 3, 'xxxx'] print(sh["str"]) # satori ''' 能够看到都发生改变了,可是这个参数有缺陷,就是会有额外的内存消耗。当咱们加上writeback=True的时候shelve会将咱们读取的对象都放到一个内存缓存当中。 好比说咱们获取了20持久化的对象,可是咱们只修改了一个,剩余的19个只是查看并无作修改,但当咱们sh.close()的时候,会将这20个对象都写回去 由于shelve不知道你会对哪一个对象进行修改,因而无论你是查看仍是修改,都会放到缓存当中,而后再一次性都写回去。 这样会形成两点: 1.对象放到内存缓存当中,等因而从新拷贝了一份,由于咱们读取文件已经到内存当中了,而shelve又把咱们使用的对象放当内存的另外一片空间中 2.写入数据,咱们明明只修改了一份数据,可是它把20份都从新写回去了,这样会形成性能上的问题,致使效率会下降。 所以加不加这个参数,由具体状况决定 '''
一样也会多出来三个文件
数据库