• 第二十一篇 json,picklz,xml模块


    Json模块

    Json模块比较简单,仅有四个方法dumps()和loads()方法,dump()和load()方法,但是却非常的常用,实用性极强。

    如果要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如xml,但更好的方法是序列化为JSON,因为json表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。

    Json不仅是标准格式,而且比xml更快,还可以直接在web页面中读取,非常方便。

    Json表示的对象就是标准的JavaScript语言的对象,Json和Python内置的数据类型对应如下:

    Json类型 Python内置类型
    {} dict
    [] list
    "string" str
    123/123.34 int/float
    true/false  True / False
    null  None
    import json
    
    dic = {'name':'chen'}
    i = 8
    s = 'hello'
    l = [1,2,3]
    
    # json.dumps 会把字符串里所有的单引号都变成双引号
    
    data_dic = json.dumps(dic)               # 第一步:把dic的值变成双引号,{"name":"chen"},第二步:再把这个值变成json的字符串:'{"name":"chen"}'
    print(data_dic)   # {"name": "chen"}   
    print(type(data_dic))  # <class 'str'>
    
    i = json.dumps(i)                        # 第一步:把i的值变成双引号,"8",第二步:再把这个值变成json的字符串:'"8"'
    print(i)        # 8 
    print(type(i))  # <class 'str'>
    
    s = json.dumps(s)                 # 第一步:把s的值变成双引号,"hello",第二步:再把这个值变成json的字符串:'"hello"'
    print(s)          # "hello"
    print(type(s))  # <class 'str'>
     
    l = json.dumps(l)                
    print(l)        #  [1, 2, 3]
    print(type(l))  #  <class 'str'>
    
    
    # 从上面的结果可以看到,json.dumps()首先会把所有数据类型的值都变成双引号(因为json只认双引号),然后再把这个值变成字符串

    dumps()和loads()方法

    # 上面已经把各种数据类型都通过json.dumps()方法处理成了json格式的字符串,然后把字符串写入到new_dic文件
    
    # json.dumps()是-----序列化
    dic = {'name':'chen'}
    dic_str = json.dumps(dic)
    f = open('new_dic','w', encoding = 'utf-8')
    f.write(dic_str)
    f.close
    
    # json.loads()是------反序列化
    # 最后再读取new_dic内的文件
    f_read = open('new_dic','r', encoding = 'utf-8')
    data  = json.loads(f_read.read())
    print(data)            #  {'name': 'chen'}
    print(type(data))      #   <class 'dict'>
    print(data['name'])    #  chen

    dump()和load()方法

    # dump()和load()可以简化dumps()和loads()的处理过程
    
    # 上面的如果要写一个字典到文件里,实现序列化,使用dumps()的代码如下:
    dic = {'name':'chen'}
    f = open('new_dic','w', encoding = 'utf-8')
    # 下面的两行会被dump()直接简化处理掉
    dic_str = json.dumps(dic)
    f.write(dic_str)
    f.close()
    
    # 而如果使用dump()方法,代码如下:
    dic = {'name':'chen'}
    f = open('new_dic','w', encoding = 'utf-8')
    json.dump(dic,f)
    f.close()
    
    
    # 同理,如果想从文件里读取内容,实现反序列化,使用loads()代码如下:
    f_read = open('new_dic','r', encoding = 'utf-8')
    data  = json.loads(f_read.read())
    
    # 而如果使用load()方法,代码如下:
    f_read = open('new_dic','r', encoding = 'utf-8')
    data = json.load(f_read)
    print(data)   # {'name': 'chen'}
    
    
    # 虽然dump()和load()可以简化dumps()和loads(),但是太定制化了,仅限于对文件的处理。 所以,建议在程序开发中还是使用dumps()和loads()方法,因为还有其他数据类型的处理呢。

    XML模块

    XML是实现不同语言或程序之间进行数据交换的协议,跟json作用差不多,但json使用起来更简单,不过,再远古时候,json未诞生的年代,只能用xml,所以,至今很多传统行业如金融行业的很多系统的接口主要还是xml.

    xml文件内容

    <data>
        <country name="Liechtenstein">        <--注释:country 是标签名, name是属性,用来解释标签用的-->
            <rank updated="yes">2</rank>      <-- 2是text,文本-->
            <year updated="yes">2010</year>
            <gdppc>141100</gdppc>
            <neighbor direction="E" name="Austria" />
            <neighbor direction="W" name="Switzerland" />
        </country>
        <country name="Singapore">
            <rank updated="yes">5</rank>
            <year updated="yes">2013</year>
            <gdppc>59900</gdppc>
            <neighbor direction="N" name="Malaysia" />
        </country>
        <country name="Panama">
            <rank updated="yes">69</rank>
            <year updated="yes">2013</year>
            <gdppc>13600</gdppc>
            <neighbor direction="W" name="Costa Rica" />
            <neighbor direction="E" name="Colombia" />
        </country>
    </data>

    Python处理xml文件

    • 遍历xml文件
    1. getroot()方法
    # 1. 先导入xml模块
    import xml.etree.ElementTree as ET
    
    # 2. parse(): 读取xml数据并解析。parse是解析的意思
    tree = ET.parse("tryxml")     # tree是个对象,对象是个实体,可以调用属性和方法
    
    
    # getroot(): root是根的意思,getroot()就是获取根节点
    root = tree.getroot()   # 获取对象的根节点
    print(root)
    # 结果
     <Element 'data' at 0x00E87330>   #凡是有地址的,一定是对象,可以对他进行操作,可以对他进行遍历,可以看它里面的信息,
    
    # 对象的第一个属性tag,tag是标签的意思      
    print(root.tag)                    
    
    # 结果: 
    data   

      2. tag  和 attrib 属性

    #上面的root打印后是个对象,那么就可以对该对象进行遍历,看它里面都有什么
    
    for i in root:
        print(i.tag)
    
    # 结果
    country
    country
    country
    
    # 再对i对象进行遍历,看它下面都有什么
    for i in root:
        for j in i:
            print(j.tag)
    
    # 结果
    rank
    year
    gdppc
    neighbor
    neighbor
    rank
    year
    gdppc
    neighbor
    rank
    year
    gdppc
    neighbor
    neighbor
    # 上面都是只得到了标签,也就是tag属性,那怎么查看标签都有什么属性呢?
    
    # attrib 属性:获取标签的属性
    for i in root:
        print(i.attrib)
    
    #结果
    {'name': 'Liechtenstein'}
    {'name': 'Singapore'}
    {'name': 'Panama'}
    
    # 获取i对象下面标签的属性
    for i in root:
        for j in i:
            print(j.attrib)
    
    #结果
    {'updated': 'yes'}
    {'updated': 'yes'}
    {}
    {'direction': 'E', 'name': 'Austria'}
    {'direction': 'W', 'name': 'Switzerland'}
    {'updated': 'yes'}
    {'updated': 'yes'}
    {}
    {'direction': 'N', 'name': 'Malaysia'}
    {'updated': 'yes'}
    {'updated': 'yes'}
    {}
    {'direction': 'W', 'name': 'Costa Rica'}
    {'direction': 'E', 'name': 'Colombia'}
    
    # text属性:获取标签实际包裹的内容
    for i in root:
        for j in i:
            print(j.text)
    
    # 结果
    2
    2010
    141100
    None
    None
    5
    2013
    59900
    None
    69
    2013
    13600
    None
    None

      3. iter()方法

    # 上面拿到的都是全部的数据,如果只想拿到所有的year节点的内容怎么取?
    # 只遍历所有year 节点,需要对根节点进行遍历
    
    # iter()方法
    for node in root.iter('year'):
        print(node.tag, node.text)    # node.tag拿到year的标签; node.text 拿到year的内容
    
    # 结果
    year 2010
    year 2013
    year 2013
    • 查找
    # 三种查找方式
    print(root.find('country'))  # find找到第一个儿子就返回了
    print(root.findall('country')) # findall找到全部儿子的才返回
    print(root.find('rank'))  # None 因为find找的是儿子,rank是孙子了,所以返回None
    • 修改xml文件
    # 修改
    for node in root.iter('year'):        # 先遍历
        new_year = int(node.text) + 1     # 再取出要修改的值,进行修改
        node.text = str(new_year)         # 把新修改的text赋值给原来的text,实现修改功能
        node.set("updated", "yes")        # 对属性进行修改,给year 标签 加了属性 updated = yes
    
    # 上面只是修改成功了,但是并没有写入文件,所以还需要进行写入操作
    
    # write():写入文件
    tree.write("xmlabc.xml")     # 写的时候重新取个名字,存为一个新的文件
    tree.write("tryxml")     # 覆盖原来的文件
    # 修改后的xml文件
    
    <data>
        <country name="Liechtenstein">
            <rank updated="yes">2</rank>
            <year updated="yes">2011</year>
            <gdppc>141100</gdppc>
            <neighbor direction="E" name="Austria" />
            <neighbor direction="W" name="Switzerland" />
        </country>
        <country name="Singapore">
            <rank updated="yes">5</rank>
            <year updated="yes">2014</year>
            <gdppc>59900</gdppc>
            <neighbor direction="N" name="Malaysia" />
        </country>
        <country name="Panama">
            <rank updated="yes">69</rank>
            <year updated="yes">2014</year>
            <gdppc>13600</gdppc>
            <neighbor direction="W" name="Costa Rica" />
            <neighbor direction="E" name="Colombia" />
        </country>
    </data>
    View Code
    • 删除xml文件节点
    # 删除node
    
    # findall():可以找多个对象
    # find():找一个对象
    # remove(): 删除对象
    # write(): 写入文件
    
    for country in root.findall('country'):
        rank = int(country.find('rank').text)
        if rank > 50:
            root.remove(country)
    
    tree.write('output.xml')
    • 创建xml数据
    # 如何通过代码生成xml呢?
    
    # 1. 导入 xml模块
    import xml.etree.ElementTree as ET
    
    # 2. 创建一个根节点,namelist是根节点的名字
    # Element():创建根节点
    # 实现的是<namelist> </namelist>
    
    new_xml = ET.Element("namelist")
    
    
    # 3. 在根节点里插入子节点
    # SubElement(): 创建子节点
    # SubElement(new_xml, "name", attrib={"enrolled": "yes"})里的new_xml 是要插入的目标;name是标签名;attrib 是 name标签的属性
    name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
    age = ET.SubElement(name, "age", attrib={"checked": "no"})
    sex = ET.SubElement(name, "sex")
    
    # 4. 给标签写入内容
    sex.text = 'male'
    age.text = '你多大了?'
    
    # 第二个name标签
    name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})
    age = ET.SubElement(name2, "age")
    age.text = '19'
    
    # 5. 生成xml文档对象
    et = ET.ElementTree(new_xml)  # 生成文档数,这句话是必不可少的
    et.write("test.xml", encoding="utf-8", xml_declaration=True)  # 最后,将生成的文件,写入文件就行了
    
    # 6. 打印生成的格式
    ET.dump(new_xml)  
    • 通过代码创建的xml文档树
    <?xml version='1.0' encoding='utf-8'?>
    <namelist>
        <name enrolled="yes">
            <age checked="no">你多大了?</age>
            <sex>female or male</sex>
        </name>
        <name enrolled="no">
            <age>19</age>
        </name>
    </namelist>
    View Code
  • 相关阅读:
    带你了解什么是Push消息推送
    小白学习如何打日志
    最近学到的前后端分离知识
    记一次愚蠢的操作--线程安全问题
    在工作中常用到的SQL
    在工作中常用的Linux命令
    记一次愚蠢的经历--String不可变性
    在公司做的项目和自己在学校做的有什么区别?
    程序员的快乐就是这么朴素无华且枯燥
    《大型网站系统与Java中间件》读书笔记 (中)
  • 原文地址:https://www.cnblogs.com/victorm/p/9252085.html
Copyright © 2020-2023  润新知