zoukankan      html  css  js  c++  java
  • python学习之路(十一)

    这一节主要讲一下【json and pickle

    先说一个例子

    假如打游戏 你花好长时间养了一个小怪兽 然后你中午去吃饭 
    你没法砍别人了 怕别人给你的小怪兽砍死 但是你又不想退出 
    因为你得养着那个小怪兽 那怎么办? —— 挂机 
     
    就是你先给它挂起 就是当前这个环境 然后多少滴血
    多少有多少宝贝 神马神马滴 。。。 kua cha 就挂起了
    就跟暂停了差不多 然后吃饭回来再给它恢复 
    恢复之后又开始相互砍 就运行起来了
     
    那还有可以举虚拟机的例子
    虚拟机 它就可以暂停 挂起 然后它也可以恢复
    之前哪个页面 哪个终端 哪个路径 神马神马滴 。。。
     
    这个是怎么实现的呢?
    它肯定是中断的时候 保存了一个什么东西
    它保存在哪里? —— 全都保存在文件里面 对 文件
     
    因为虚拟机运行 是在内存运行的 保存文件的时候
    是从内存里面 把状态数据拷贝一个镜像 放到磁盘上面
     
    内存里面的东西 它不仅仅是字符串 它可以有其它的数据类型 
    比如 字典 列表 函数 类 这些东西 
    但是保存在文件里 文件它只能保存字符串 或者说是二进制码 
     
    f = open('file.txt', 'w')

    info = {
    'name':'lucia',
    'age':18
    }

    f.write(info)

    f.close()
    这段代码 它先 open 一个文件 f
    然后有一个字典 info
    把字典写入文件 —— 报错:
    第二阶段 15 json and pickle 序列化 - Lucia - Lucias WorkShop
     
    报错意思是 write 到文件 必须是 str 不能是 dict
     
    那这个好办 —— 强制转换成字符串:
    f.write(str(info))
    然后代码不报错了 而且也存进去了:
    第二阶段 15 json and pickle 序列化 - Lucia - Lucias WorkShop
     
    就是说 文件它只能保存字符串 不能存字典神马神马滴
     
    存进去之后 还要恢复才行
    现在把一个内存里面的字典的数据类型 变成字符串 
    然后存到了磁盘上 —— 这个过程叫做序列化
    有序列化 就肯定有反序列化 —— 就是在加载回内存里面
     
    在一个新的程序里面 打开刚才那个文件
    f = open('file.txt', 'r')
    然后读进来 
    data = f.read()
    print(data)
    第二阶段 15 json and pickle 序列化 - Lucia - Lucias WorkShop
     
    读进来还不是最终目的 因为它是以字符串形式读进来的 没办法操作
    还记得那个 eval 吧
    data = eval(f.read())
    这样子 确实是可以解决问题的
     
    那还有没有其它办法呢?
    因为除了 eval 之外 还有更通用 更标准 更规范的办法
    —— 就是反序列化 json
    它序列化的时候 要写到文件 但并不是像 str 那样强制转换的
    f.write(json.dumps(info))
    这样子的
    然后反序列化的时候 再 import json
    data = json.loads(f.read())
    这样子 就反序列化到内存里面去了
     
    所以序列化是 dumps 反序列化是 loads
    内存 --- 磁盘 --- 内存
    运行 --- 挂起 --- 运行
    就这个过程 很简单 容易理解
     
    毕竟 现在从内存挂起 和从磁盘恢复的 只是一个字典
    如果是 函数 又会怎样
    import json

    def sayhi(name):
    print('hello, ', name)

    info = {
    'name':'lucia',
    'job':'it',
    'func':sayhi
    }

    f = open('lucia_de_file', 'w')

    f.write(json.dumps(info))

    f.close()
    这样子会触发报错:
    TypeError: Object of type 'function' is not JSON serializable
    意思是:函数类型 不是可序列化的类型
    所以 json 它只能处理简单的数据类型 字典啊 列表啊 字符串啊 这些简单的
     
    原因是 json 是在各种语言之间通用的 它负责各种语言之间的数据交互
    就比方说 python 程序要和 java 程序交互 和 PHP 程序交互 等等
     
    交互的时候 把 Python 的字典转成 Java 的字典
    把 Java 的列表转成 Python 的列表
    所以 不可以太复杂 只能是简单的
     
    再说一句 xml 它正在逐渐被 json 取代
    因为 xml 它主要的作用 也是在语言之间完成数据交互
    但是 json 的好处在于 它看上去很容易看懂 很清晰 
    并且 不需要额外的标签之类的东西 来做很多的描述
     
    最终 xml 必将被 json 完全取代
    但是不管是 xml 还是 json 能处理的 都是简单的类型
     
    那如果就是要处理复杂的类型怎么办
    那就不是 json 了 换成 pickle 用法完完全全一样 就行了
    import pickle
    f = open('lucia_de_file', 'wb')
    f.write(pickle.dumps(info))
    运行就没有毛病 正常生成了 lucia_de_file
     
    然后反序列化 也是 pickle
    import pickle

    f = open('lucia_de_file', 'rb')

    data = pickle.loads(f.read())

    print(data)
    这样子 遭遇的报错是:

    AttributeError: Can't get attribute 'sayhi' on <module '__main__' from '/Users/lucia_gaga/PycharmProjects/practice_lucia/222.py'>

    这个原因是 你需要把函数的内存地址 反序列化到内存中去
    但是刚才序列化的时候 得到的内存地址 没了 
    运行完了 就没了 所以根本就不应该这样写反序列化的代码
     
    把 sayhi 函数的代码 拷贝过来 它的内存地址就不会丢了:
    第二阶段 15 json and pickle 序列化(下) - Lucia - Lucias WorkShop
     
    这样子 就完成了反序列化
     
    还有一种写法是
    pickle.dump(info, f)
    以及
    pickle.load(f)
    序列化一次 & 反序列化一次
    f.write(json.dumps(info))

    info['job'] = 'qa'
    f.write(json.dumps(info))
    两次序列化之间 改一个值 然后结果:
    第二阶段 15 json and pickle 序列化(下) - Lucia - Lucias WorkShop
     
    然后再看反序列化:
    会报错
     
    它的意思是 只能 dump 一次 然后 load 一次 不能多次
     
     
    还记得虚拟机快照吗
    它其实是 每个镜像保存为一个文件 而不是一个文件里面放好多内容
  • 相关阅读:
    如何写一个使用Web Service的IOS应用
    iPad定制相机界面
    IOS Quartz 2D 学习(1)
    cocoa Shallow Copy与Deep Copy
    sqlite3_prepare_v2返回1
    IOS 监听相机对焦事件
    UIImageView添加响应事件无响应
    二、Mongodb常用命令
    三、Mongodb Java中的使用
    多测师肖老师__第二个月python安装和pycharm安装
  • 原文地址:https://www.cnblogs.com/lovelyming/p/7266213.html
Copyright © 2011-2022 走看看