Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式

Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式

 

目录

Pycharm使用技巧(转载)

Python第一天  安装  shell  文件

Python第二天  变量  运算符与表达式  input()与raw_input()区别  字符编码  python转义符  字符串格式化

Python第三天 序列  5种数据类型  数值  字符串  列表  元组  字典

Python第四天   流程控制   if else条件判断   for循环 while循环

Python第五天   文件访问    for循环访问文件    while循环访问文件   字符串的startswith函数和split函数

Python第六天   类型转换

Python第七天   函数  函数参数   函数变量   函数返回值  多类型传值    冗余参数   函数递归调用   匿名函数   内置函数   列表表达式/列表重写

Python第八天  模块   包   全局变量和内置变量__name__    Python path

Python第九天  面向对象  类定义   类的属性    类的方法    内部类   垃圾回收机制   类的继承 装饰器

Python第十天   print >> f,和fd.write()的区别    stdout的buffer  标准输入 标准输出  标准错误   重定向 输出流和输入流

Python第十一天    异常处理  glob模块和shlex模块    打开外部程序和subprocess模块  subprocess类  Pipe管道  operator模块   sorted函数   生成器  walk模块   hashlib模块

Python第十二天     收集主机信息     正则表达式  无名分组   有名分组

Python第十三天   django 1.6   导入模板   定义数据模型   访问数据库   GET和POST方法    SimpleCMDB项目   urllib模块   urllib2模块  httplib模块  django和web服务器整合  wsgi模块   gunicorn模块

Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式

Python第十五天  datetime模块 time模块   thread模块  threading模块  Queue队列模块  multiprocessing模块  paramiko模块  fabric模块  

 

 

 

python中的任何数据类型都可以dump成json格式

 

https://www.birdpython.com/posts/2/47/

简单序列化
序列化
将对象的状态信息转换为可以存储或传输的形式的过程
不但读写磁盘需要通过文件对象,网络传输数据也需要通过文件对象,因为网络 IO 是指通过文件对象去读写网卡而已,磁盘 IO 是指通过文件对象读写磁盘而已。我们知道文件对象只能处理字符流,如果我们想把非字符类型数据(int,float,bool,list,tuple,dict等等)通过网络发到其他机器或保存到本地文件,那就需要序列化
把变量从内存中变成可存储或传输的过程(也就是变成字符流的过程)
把序列化后的字符流还原成序列化之前的类型数据的过程叫反序列化

 

最典型场景是
1、很多游戏允许你在退出的时候保存进度,序列化到磁盘,然后你再次启动的时候反序列化回到上次退出的地方
2、序列化为json,在网络上传输

 

常用的一些序列化
pickle、cPickle 这两个模块用法差不多,cpickle模块,C语言实现,速度是pickle的1000倍,可以先尝试导入cpickle不行再导入pickle
JSON
Shelve
YAML

 


 

pickle模块
所有python支持的类型都可以用pickle做序列化

dump(obj, file, protocol=None)
obj:表示序列化的对象,处理循环,递归引用对象,类,函数,类的实例
file:支持write()方法的文件句柄,可以是真实文件,也可以StringIO对象
protocol:序列化协议,0表示ascii协议,ascii码表示,1表示老的二进制协议,2表示新二进制协议,默认为0

 

pickle的方法
dump保存到磁盘
dumps保存到内存
load 读到磁盘
loads 读到内存



try:
    import cPickle as pickle
except ImportError:
    import pickle

mylist = [1, True, "hello"]
seqdata = pickle.dumps(mylist)   # 序列化成字符流
print(type(seqdata))             # list 类型数据 序列化成 str 类型
print(seqdata)                   # 序列化后的字符流

mylistreseq = pickle.loads(seqdata)  # 把被序列化的字符流反序列化成 list
print(type(mylistreseq))             # list 类型
print(mylistreseq)                   # 反序列化后的 list

 

 

 

在 Python 3 中,把用 pickle 序列化后的字符流存储到磁盘,必须以 wb 的形式;同样,从磁盘上读取用 pickle 序列化后的字符流用 rb 的形式。

try:
    import cPickle as pickle
except ImportError:
    import pickle

mylist = [1, True, ("hello", None)]
f = open("d:/test.txt", "wb")
seqdata = pickle.dumps(mylist)       # 序列化成字符流
f.write(seqdata)
f.close()

f = open("d:/test.txt", "rb")
seqdata = f.read()
f.close()
mylistreseq = pickle.loads(seqdata)  # 反序列化后的 list
print(mylistreseq)

 

 

对于我们自定义类型,同样可以使用 pickle 进行序列化。

try:
    import cPickle as pickle
except ImportError:
    import pickle

class myclass(object):
    def __init__(self):
        self.data = 250

    def func(self):
        print("ok")

myobject = myclass()
xx = pickle.dumps(myobject)

yy = pickle.loads(xx)
print(yy.data)
yy.func()

 

 

 


 

json模块

序列化对象供其他语言读写
JavaScript Object Notation
Json是被设计为跨语言使用的
Json是字符串格式
默认utf-8方式存储

 

这个模块可以把不同语言的数据类型序列化成统一的数据类型,然后反序列成相应语言的数据类型, 这个模块就是 json 模块,json 就如英文一样,如果中文和日文需要交流,可以先翻译成英文,然后在翻译成自己的语言

javascript,json的key必须用用双引号引住字符串,不能用单引号

 

 

json序列化
json.dump() 其他格式数据转为json到磁盘
json.dumps() 其他格式数据转为json到内存

ensure_ascii=True:json只能ascii编码,同样,pickle模块的dump(obj, file, protocol=None),protocol:序列化协议,0表示ascii协议,ascii码表示,默认为0
indent:缩进,让打印出来的json字符串更好看print json.dumps(data, indent=2)
encoding='utf-8':默认utf-8编码,utf-8传进来-》ascii
default :自定义类json序列化时的处理函数
def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        encoding='utf-8', default=None, sort_keys=False, **kw):

 

 

json.load() 从磁盘读json转为其他格式数据 

json.loads() 从内存读json转为其他格式数据 

encoding=None:load方法可能无法处理中文字符,需要通过encoding参数指定字符编码,如果dumps()方法encoding时候的不是utf-8,需要指定一下编码
object_hook:自定义类反序列化时候的处理函数
def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
        

 

 

数据保存至JSON文件

    import json

    # 序列化
    d = {}
    d['a'] = 'a'
    d['b'] = 235
    d['c'] = ('c1', 'c2')
    d['d'] = True
    d['e'] = None
    with open('/tmp/d.json', mode='w') as fd:
        json.dump(d, fd)

 

反序列化

    with open('/tmp/d.json') as fd:
        d1 = json.load(fd)


传递json格式的数据
定义url和方法

    def collectjson(req):
        if req.POST:
            jsonobj = json.loads(req.body)
            host = Host()
            host.hostname = jsonobj['hostname']
            host.vendor = jsonobj['vendor']
            host.product = jsonobj['product']
            host.save()

 

 


json 肯定只能支持所有语言都共有的数据类型,比如 int,float,bool 等这些类型,但是并不是所有语言的类型都是一样的,比如 Python 的 set 类型在其它语言中就没有,json 就不会支持对这种类型数据的序列化和反序列化。

import json

myset = set([3, 4, 5])
data = json.dumps(myset)    # 错误

 

Python 中的 tuple 类型在其它语言中也没有,但是 tuple 类型和 list 类型很相似,所以 json 会把 tuple 类型数据序列化和反序列化成 Python 的 list 类型数据。 如果是用其它语言进行反序列化我们序列化好的 Python 中的 tuple 类型数据,则会反序列化成其它语言对应的数组类型。

import json

mytuple = (1, 2, 4)
data = json.dumps(mytuple)
dd = json.loads(data)
print(type(dd))  # <type 'list'>
print(dd)        # [1, 2, 4]

 

 


Python 中的 dict 类型在其它语言中有类似的类型,比如 C++ 中的 map,Js 中的 object 等等,但是他们的格式有些不同,比如 C++ 中的 map 的键只允许字符串类型等等。我们用 json 序列化和反序列化 Python 的 dict 类型数据,就会只支持键为字符串的 dict,如果键是其它基本数据类型 json 模块会把他转为相应的字符串,如果是 tuple 类型则会报错。

import json

seqdata = json.dumps({1: 1, 1.1: 2, "a": 3, None: 4, True: 5})  # 序列化成字符流,并且对不是字符串类型的键做强制转换
dd = json.loads(seqdata)
print(dd)  # {u'a': 3, u'1': 5, u'null': 4, u'1.1': 2}

seqdata = json.dumps({(1,2): 1})  # 虽然字典本身没问题,但是使用 json 序列化会报错

 

 

Python 的数据类型对应的 json 数据类型的关系图,当然其它语言的数据类型也对应这同样的 json 数据类型

 

我们自定义的类对象是否可以用 json 序列化呢,比如我们定义一个 Human 类,然后对 Human 类的对象进行序列化

import json

class Human(object):
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

oneman = Human('如花', 18, "")
seqdata = json.dumps(oneman)  # 抛出异常,...is not JSON serializable

上面的代码之所以无法把 Human 类对象序列化为 json,是因为默认情况下,json 模块中的 dumps 函数不知道如何将 Human 对象变为一个 json 对象。 dumps 函数的可选参数 default 就是把任意一个对象变成一个可序列为 json 的对象,我们只需要为 Human 类专门写一个转换函数,再把函数传进去即可

import json

class Human(object):
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

def human2dict(oneman):
    return {
    'name': oneman.name,
    'age': oneman.age,
    'sex': oneman.sex
    }

oneman = Human('如花', 18, "")
print(json.dumps(oneman, default=human2dict))

因为通常类的对象都有一个 __dict__ 属性,它就是一个 dict,用来存储实例变量。也有少数例外,比如定义了 __slots__ 的 类。同样的道理,如果我们要把 json 反序列化为一个 human 类的对象,json 模块的 loads 函数首先转换出一个 dict 对象,然后,我们传入的 object_hook 函数负责把 dict 转换为 human 类的对象。

import json

class Human(object):
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

def human2dict(oneman):
    return {
    'name': oneman.name,
    'age': oneman.age,
    'sex': oneman.sex
    }

def dict2human(d):
    return Human(d['name'], d['age'], d['sex'])

oneman = Human('如花', 18, "")
print(json.dumps(oneman, default=human2dict))

json_str = '{"name": "如花", "age": 18, "sex": "女"}'
print(json.loads(json_str, object_hook=dict2human))

 

我们仔细思考一下,自定义对象的属性是什么,其实自定义对象的属性最终还是由 Python 内置的数据类型表示的。我们对自定义对象进行序列化,本质是就是对对象的所有属性进行序列化,这些属性最终是由 Python 内置的数据类型表示的,我们只需要序列化这些数据就可以了,无论我们是把这些序列化后的数据存储在磁盘上 还是通过网络发送给其它机器,只需要存储或发送对象的所有属性即可

import json

class Human(object):
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

oneman = Human('如花', 18, "")
onemandata = {"name": oneman.name, "age": oneman.age, "sex": oneman.sex}

seqdata = json.dumps(onemandata)  # 序列化对象含有的属性
print(seqdata)

reseqonemandata = json.loads(seqdata)  # 反序列化
print(reseqonemandata)

 

 


 

时间转为json的两个解决方法

To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
``.default()`` method to serialize additional types), specify it with
the ``cls`` kwarg; otherwise ``JSONEncoder`` is used.cls代表类本身

``default(obj)`` is a function that should return a serializable version
of obj or raise TypeError. The default simply raises TypeError.

1、用类

def test(self):
    js = {
        'test5': datetime.datetime.now(),
    }
    print(js)
    result = json.dumps(js, cls=CJsonEncoder)
    print(result)



class CJsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, datetime.date):
            return obj.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, obj)

2、用函数

def json_serial(obj):
    if isinstance(obj,datetime.datetime):
        serial=obj.isoformat()
        return serial
    elif isinstance(obj,datetime.date):
        serial=obj.isoformat()
        return serial
    else:
        return json.JSONEncoder.default(obj)



js = {
    'test5': datetime.datetime.now(),
}
print json.dumps(js, default=json_serial)

 

posted @ 2017-02-14 17:31  桦仔  阅读(1626)  评论(0编辑  收藏  举报