pickle,shelve,json,configparser 的模块使用
主要内容
1. 什么是序列化
2. pickle
3. shelve
4. json
5. configparser模块
一. 什么是序列化
在我们存储数据或者网络传输数据的时候. 需要对我们的对象进行处理. 把对象处理成
方便存储和传输的数据格式. 这个过程叫>>>序列化<<<. 不同的序列列化, 结果也不同. 但是目的是一样的. 都是为了存储和传输.
在python中存在三种序列化的方案.
◎1. pickle. 可以将我们python中的任意数据类型转化成bytes并写入到文件中. 同样也可以把文件中写好的bytes转换回我们python的数据. 这个过程被称为反序列化
◎2. shelve. 简单另类的一种序列化的方案. 有点儿类似后面我们学到的redis. 可以作为一种小型的数据库来使用
◎3. json. 将python中常见的字典, 列表转化成字符串. 是目前后端数据交互使⽤用频率最高的一种数据格式.
二. pickle
pickle用起来很简单. 说白了. 就是把我们的python对象写入到文件中的一种解决方案.
但是写入到文件的是bytes. 所以这东西不是给人看的. 是给机器看的.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import pickle # dumps 序列化。 把对象转化成bytes<br># loads 反序列化。 把bytes转化成对象<br># dump 序列化。 把对象转化成bytes并写入文件<br># load 反序列化。把文件中的bytes读取。转化成对象class Cat: def __init__( self , name, age): self .name = name self .age = age def catchMouse( self ): print ( self .name, "抓老鼠" ) c = Cat( "jerry" , 18 ) bs = pickle.dumps(c) # 序列化一个对象. print (bs) # 一堆二进制. 看不懂 cc = pickle.loads(bs) # 把二进制反序列化成我们的对象 cc.catchMouse() # 猫依然是猫. 还可以抓老鼠 |
★pickle中的dumps可以序列化一个对象. loads可以反序列化一个对象. 我们使用dump还可以直接 把一个对象写入到文件中:
1 2 3 4 5 6 7 | # f = open("cat", mode="wb") # pickle.dump(c, f) # 写入到文件中 # f.close() f = open ( "cat" , mode = "rb" ) cc = pickle.load(f) # 从文件中读取对象 cc.catchMouse() |
★pickle还⽀支持多个对象的写出:
1 2 3 4 5 6 7 8 9 10 11 | #1.<br>lst = [Cat("jerry", 19), Cat("tommy", 20), Cat("alpha", 21)] f = open ( "cat" , mode = "wb" ) for el in lst: pickle.dump(el, f) # 写入到文件中 f.close() f = open ( "cat" , mode = "rb" ) for i in range ( len (lst)): cc = pickle.load(f) # 从文件中读取对象 cc.catchMouse()<br><br><br> #+2.<br>lst = [Cat("猫1", 10), Cat("猫2", 9), Cat("猫3", 8), Cat("猫4", 7), Cat("猫5", 6)]f = open("pickle-test", mode="wb")<br>pickle.dump(lst, f)<br>for el in lst:<br> pickle.dump(el, f)<br><br>f.flush()<br>f.close() |
◆但是这样写并不够好. 因为读的时候. 并不能知道有多少对象要读. 这里记住, 不能一行一行的读. 那真的要写入或者读取多个内容怎么办? 很简单. 装lis里. 然后读取和写入都用list
1 | lst = [Cat( "jerry" , 19 ), Cat( "tommy" , 20 ), Cat( "alpha" , 21 )]f = open ( "pickle-test" , mode = "rb" )<br> while 1 :<br> try :<br> c1 = pickle.load(f)<br> c1.catchMouse()<br> except EOFError:<br> break |
记住一点, pickle序列化的内容是二进制的内容(bytes) 不是给人看的.
三. shelve
shelve提供python的 >>>持久化<<< 操作. 什么叫持久化操作呢? 说白话,就是把数据写到硬盘上.
在操作shelve的时候非常的像操作一个字典. 这个东西到后期. 就像redis差不多.
1 2 3 4 5 6 | import shelve shelf = shelve. open ( "sylar" ) # shelf["jay"] = "周杰伦" print (shelf[ 'jay' ]) shelf.close()<br><br>s = shelve. open ( "sylar" )<br> # s["jay"] = {"name":"周杰伦", "age":18, "hobby":"哄小孩"}<br>print(s['jay'])<br>s.close()<br><br># 但是, 有坑<br>s = shelve.open("sylar")<br>s['jay']['name'] = "胡辣汤" # 尝试改变字典中的数据<br>s.close()<br>s = shelve.open("sylar")<br>print(s['jay']) # 并没有改变<br>s.close()<br># 解决方案:<br>s = shelve.open("sylar", writeback=True)<br>s['jay']['name'] = "胡辣汤" # 尝试改变字典中的数据<br>s.close()<br>s = shelve.open("sylar")<br>print(s['jay']) # 改变了.<br>s.close() |
★ writeback=True 可以动态的把我们修改的信息写入到文件中. 而且还可以删除数据. 就像字典一样. 上一波操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | s = shelve. open ( "sylar" , writeback = True ) del s[ 'jay' ] s.close()<br> s = shelve. open ( "sylar" ) print (s[ 'jay' ]) # 报错了, 没有了 s.close()<br> s = shelve. open ( "sylar" , writeback = True ) s[ 'jay' ] = "周杰伦" s[ 'wlj' ] = "王力宏" s.close()<br> s = shelve. open ( "sylar" ) for k in s: # 像字典一样遍历 print (k) print (s.keys()) # 拿到所有key的集合 for k in s.keys(): print (k) for k, v in s.items(): # 像字典一样操作 print (k, v) s.close() |
综上 shelve 就当成字典来用就行了. 它比redis还简单.......
四. ★☆★ ☆ json ☆★☆★
json是我们前后端交互的枢纽. 相当于编程界的普通话. 大家沟通都用json. 为么这样呢? 因为json的语法格式可以完美的表示出一个对象. 那么是json: json 全称 >>>javascript object notation . 翻译过来叫js对象简谱. 很复杂是吧? 来上一段简单的代码:
1 2 3 4 5 6 7 8 9 10 | wf = { "name" : "汪峰" , "age" : 18 , "hobby" : "上头条" , "wife" :{ "name" : '⼦子怡' , "age" : 19 , "hobby" :[ "唱歌" , "跳舞" , "演戏" ] } } |
这个不是字典么? 对的. 在python里这叫字典. 但是在javascript里这叫 json. 一模一样的. 我们发现用这样的数据结构可以完美的表示出任何对象. 并且可以完整的把对象表示出来. 只要代码格式比较好. 那可读性也是很强的. 所以大家公认用这样一种数据结构作为数据交互的格式. 那在这个东西之前是什么呢? XML.....来看⼀一段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version = "1.0" encoding = "utf-8" ?> <wf> <name>汪峰< / name> <age> 18 < / age> <hobby>上头条< / hobby> <wife> <name>⼦子怡< / name> <age> 18 < / age> <hobbies> <hobby>唱歌< / hobby> <hobby>跳舞< / hobby> <hobby>演戏< / hobby> < / hobbies> < / wife> < / wf> |
古人(老程序员)都是用这样的数据进行传输的. 先不管这个东西好不好看. 这玩意想要解析.. 那简直了. 想死的心都有. 所以老版本的xml在维护和处理理上是非常复杂和繁琐的. 以前的项目几乎没有用ajax的.
那json既然这么牛B好⽤用. 怎么用呢? 注意. 这里又出来一个新问题. 我们的程序是在python⾥里写的. 但是前端是在JS那边来解析json的. 所以. 我们需要把我们程序产生的字典转化成json格式的json串(字符串). 然后网络传输. 那边接收到了之后. 它爱怎么处理是它的事情. 那, 如何把字典转化成我们的json格式的字符串呢?很简单, 上代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import json dic = { "a" : "女王" , "b" : "萝莉" , "c" : "小清新" } s = json.dumps(dic) # 把字典转化成json字符串 print (s) # {"a": "\u5973\u738b", "b": "\u841d\u8389", "c":"\u5c0f\u6e05\u65b0"}<br> # 结果很不友好啊. 那如何处理中文呢? 在dumps的时候给出另一个参数ensure_ascii=False就可以了 import json dic = { "a" : "女王" , "b" : "萝莉" , "c" : "小清新" } s = json.dumps(dic, ensure_ascii = False ) # 把字典转化成json字符串 print (s) # {"a": "女王", "b": "萝莉", "c": "小清新"}<br><br> # 假如,前端给你传递信息了. 你要把前端传递过来的json字符串转化成字典: import json s = '{"a": "女王", "b": "萝莉", "c": "小清新"}' dic = json.loads(s) print ( type (dic), dic)<br> # json也可以像pickle一样把序列化的结果写入到文件中. dic = { "a" : "女王" , "b" : "萝莉" , "c" : "小清新" } f = open ( "test.json" , mode = "w" , encoding = "utf-8" ) json.dump(dic, f, ensure_ascii = False ) # 把对象打散成json写入到文件中 f.close() 同样也可以从文件中读取一个json f = open ( "test.json" , mode = "r" , encoding = "utf-8" ) dic = json.load(f) f.close() print (dic)<br> # ★ 注意. 我们可以向同一个文件中写入多个json串. 但是读不行. import json lst = [{ "a" : 1 }, { "b" : 2 }, { "c" : 3 }] f = open ( "test.json" , mode = "w" , encoding = "utf-8" ) for el in lst: json.dump(el, f) f.close()<br> # 注意, 此时文件中的内容是一行内容: # >>> {"a": 1}{"b": 2}{"c": 3}<br> # 这在读取的时候是无法正常读取的. 那如何解决呢? 两套⽅方案. 方案一. 把所有的内容准备好统一 # 进行写入和读取. 但这样处理, 如果数据量小还好. 数据量大的话, 就不够友好了. 方案二. 不用dump. <br># 改用dumps和loads. 对每一行分别进行处理:<br> import json lst = [{ "a" : 1 }, { "b" : 2 }, { "c" : 3 }]<br> # 写入的时候<br># 1. 循环<br># 2. 用dumps把字典转化成字符串, 然后手工在后面加一个\n<br># 3. 写出<br><br>f = open("test.json", mode="w", encoding="utf-8") <br>for el in lst: <br> s = json.dumps(el, ensure_ascii=True) + "\n" <br> f.write(s) <br>f.close()# 读取的时候<br># 1. for line in f:<br># 2. strip()去掉空白<br># 3. loads()变成字典f = open("test.json", mode="r", encoding="utf-8") <br>for line in f: <br> dic = json.loads(line.strip())<br> print(dic)<br>f.close() |
五. configparser模块
该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或多个节(section)每个节
可以有多个参数(键=值).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | [DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes<br> [[ bitbucket.org]] User = hg<br> [[ topsecret.server.com]] Port = 50022 ForwardX11 = no<br> # 我们用configparser就可以对这样的文件进行处理.首先, 是初始化 import configparser<br><br>config = configparser.ConfigParser() config[ 'DEFAULT' ] = { "sleep" : 1000 , "session-time-out" : 30 , "user-alive" : 999999 }<br> config[ 'TEST-DB' ] = { "db_ip" : "192.168.17.189" , "port" : "3306" , "u_name" : "root" , "u_pwd" : "123456" }<br> config[ '168-DB' ] = { "db_ip" : "152.163.18.168" , "port" : "3306" , "u_name" : "root" , "u_pwd" : "123456" }<br> config[ '173-DB' ] = { "db_ip" : "152.163.18.173" , "port" : "3306" , "u_name" : "root" , "u_pwd" : "123456" }<br> f = open ( "db.ini" , mode = "w" ) config.write(f) # 写入文件 f.flush() f.close()<br> # 读取文件信息: config = configparser.ConfigParser()<br> config.read( "db.ini" ) # 读取文件 print (config.sections()) # 获取到section. 章节...DEFAULT是给每个章节都配备的信息 print (config.get( "DEFAULT" , "SESSION-TIME-OUT" )) # 从xxx章节中读取到xxx信息 # ◆ 也可以像字典一样操作 print (config[ "TEST-DB" ][ 'DB_IP' ]) print (config[ "173-DB" ][ "db_ip" ])<br> for k in config[ '168-DB' ]: print (k) for k, v in config[ "168-DB" ].items(): print (k, v)<br> print (config.options( '168-DB' )) # 同for循环,找到'168-DB'下所有键 print (config.items( '168-DB' )) #找到'168-DB'下所有键值对 print (config.get( '168-DB' , 'db_ip' )) # 152.163.18.168 get方法Section下的key对应的value <br> # ◆ 增删改操作: # ◎ 先读取. 然后修改. 最后写回文件 config = configparser.ConfigParser() config.read( "db.ini" ) # 读取文件 (全部都读出来了)<br> # 添加一个章节 # config.add_section("189-DB") # config["189-DB"] = { # "db_ip": "167.76.22.189", # "port": "3306", # "u_name": "root", # "u_pwd": "123456" # } # 修改信息 config. set ( "168-DB" , "db_ip" , "10.10.10.168" )<br> # 删除章节 config.remove_section( "173-DB" )<br> # 删除元素信息 config.remove_option( "168-DB" , "u_name" )<br> # ◎ 写回⽂文件 config.write( open ( "db.ini" , mode = "w" )) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)