python教程10、模块之json,pickle,xml,pyyaml,shutil,configparser
序列化
Python中用于序列化的两个模块
- json 用于【字符串】和 【python基本数据类型】 间进行转换
- pickle 用于【python特有的类型】 和 【python基本数据类型】间进行转换
Json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load
json模块
# json()将字符串形式的列表或字典转换为list或dict类型,json是所有语言相互通信的方式
# 注意外层字符形式一定是\'\'单引号,\'{"a":"xiao","b":"xiao"}\'列表或字典中的字符串一定要""双引号,否则报错
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import json
# json.dumps() 将python基本数据类型转化成字符串形式dic = {\'k1\':\'v1\'}
print(dic,type(dic))
result = json.dumps(dic)
print(result,type(result))
# json.loads() 将python字符串形式转化成基本数据类型s = \'{"k1":123}\'
dic = json.loads(s)
print(dic,type(dic))
# json.dump() 先序列化,再写入文件li = [11,22,33]
json.dump(li,open(\'db\',\'w\'))
# json.load() 读取文件反序列化l = json.load(open(\'db\',\'r\'))
print(l,type(l))
|
pickle模块
pickple只有python才能用,用于复杂类型的序列化,(如果是序列化一个对象,在别的模块中反序列化的时候一定要导入该对象所属的类,否则报错)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import pickle
# pickle.dumps() 序列化li = [11,22,33]
r = pickle.dumps(li)
print(r)
# pickle.loads() 反序列化result = pickle.loads(r)
print(result,type(result))
# pickle.dump() 先序列化,再写入文件l1 = [11,22,33,55]
pickle.dump(l1,open(\'db\',\'wb\'))
# pickle.load() 读取文件反序列化result1 = pickle.load(open(\'db\',\'rb\'))
print(result1,type(result1))
|
XML模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml,XML文件格式如下:
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2023</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="W" name="Switzerland" />
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2026</year>
<gdppc>59900</gdppc>
<neighbor direction="N" name="Malaysia" />
</country>
<country name="Panama">
<rank updated="yes">69</rank>
<year>2026</year>
<gdppc>13600</gdppc>
<neighbor direction="W" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>
1、解析XML两种方法
(1)利用ElementTree.XML将字符串解析成xml对象
|
1
2
3
4
5
6
7
|
from xml.etree import ElementTree as ET
# 打开文件,读取XML内容str_xml = open(\'xo.xml\', \'r\').read()
# 将字符串解析成xml特殊对象,root代指xml文件的根节点root = ET.XML(str_xml)
|
(2)利用ElementTree.parse将文件直接解析成xml对象
|
1
2
3
4
5
6
7
|
from xml.etree import ElementTree as ET
# 直接解析xml文件tree = ET.parse("xo.xml")
# 获取xml文件的根节点root = tree.getroot()
|
2、操作XML
XML格式类型是节点嵌套节点,对于每一个节点均有以下功能,以便对当前节点进行操作:
由于 每个节点 都具有以上的方法,并且在上一步骤中解析时均得到了root(xml文件的根节点),so 可以利用以上方法进行操作xml文件。
(1)遍历XML文档的所有内容
|
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
|
from xml.etree import ElementTree as ET
############ 解析方式一 ############"""# 打开文件,读取XML内容str_xml = open(\'xo.xml\', \'r\').read()# 将字符串解析成xml特殊对象,root代指xml文件的根节点root = ET.XML(str_xml)"""############ 解析方式二 ############# 直接解析xml文件tree = ET.parse("xo.xml")
# 获取xml文件的根节点root = tree.getroot()
### 操作# 顶层标签print(root.tag)
# 遍历XML文档的第二层for child in root:
# 第二层节点的标签名称和标签属性
print(child.tag, child.attrib)
# 遍历XML文档的第三层
for i in child:
# 第二层节点的标签名称和内容
print(i.tag,i.text)
|
(2)遍历XML中指定的节点
|
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
|
from xml.etree import ElementTree as ET
############ 解析方式一 ############"""# 打开文件,读取XML内容str_xml = open(\'xo.xml\', \'r\').read()# 将字符串解析成xml特殊对象,root代指xml文件的根节点root = ET.XML(str_xml)"""############ 解析方式二 ############# 直接解析xml文件tree = ET.parse("xo.xml")
# 获取xml文件的根节点root = tree.getroot()
### 操作# 顶层标签print(root.tag)
# 遍历XML中所有的year节点for node in root.iter(\'year\'):
# 节点的标签名称和内容
print(node.tag, node.text)
|
(3)修改节点内容
由于修改的节点时,均是在内存中进行,其不会影响文件中的内容。所以,如果想要修改,则需要重新将内存中的内容写到文件。
解析字符串方式,修改,保存
|
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
|
from xml.etree import ElementTree as ET
############ 解析方式一 ############# 打开文件,读取XML内容str_xml = open(\'xo.xml\', \'r\').read()
# 将字符串解析成xml特殊对象,root代指xml文件的根节点root = ET.XML(str_xml)
############ 操作 ############# 顶层标签print(root.tag)
# 循环所有的year节点for node in root.iter(\'year\'):
# 将year节点中的内容自增一
new_year = int(node.text) + 1
node.text = str(new_year)
# 设置属性
node.set(\'name\', \'alex\')
node.set(\'age\', \'18\')
# 删除属性
del node.attrib[\'name\']
############ 保存文件 ############tree = ET.ElementTree(root)
tree.write("newnew.xml", encoding=\'utf-8\')
|
解析文件方式,修改,保存
|
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
|
from xml.etree import ElementTree as ET
############ 解析方式二 ############# 直接解析xml文件tree = ET.parse("xo.xml")
# 获取xml文件的根节点root = tree.getroot()
############ 操作 ############# 顶层标签print(root.tag)
# 循环所有的year节点for node in root.iter(\'year\'):
# 将year节点中的内容自增一
new_year = int(node.text) + 1
node.text = str(new_year)
# 设置属性
node.set(\'name\', \'alex\')
node.set(\'age\', \'18\')
# 删除属性
del node.attrib[\'name\']
############ 保存文件 ############tree.write("newnew.xml", encoding=\'utf-8\')
解析文件方式,修改,保存 |
(4)删除节点
解析字符串方式打开,删除,保存
|
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
|
from xml.etree import ElementTree as ET
############ 解析字符串方式打开 ############# 打开文件,读取XML内容str_xml = open(\'xo.xml\', \'r\').read()
# 将字符串解析成xml特殊对象,root代指xml文件的根节点root = ET.XML(str_xml)
############ 操作 ############# 顶层标签print(root.tag)
# 遍历data下的所有country节点for country in root.findall(\'country\'):
# 获取每一个country节点下rank节点的内容
rank = int(country.find(\'rank\').text)
if rank > 50:
# 删除指定country节点
root.remove(country)
############ 保存文件 ############tree = ET.ElementTree(root)
tree.write("newnew.xml", encoding=\'utf-8\')
|
解析文件方式打开,删除,保存
|
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
|
from xml.etree import ElementTree as ET
############ 解析文件方式 ############# 直接解析xml文件tree = ET.parse("xo.xml")
# 获取xml文件的根节点root = tree.getroot()
############ 操作 ############# 顶层标签print(root.tag)
# 遍历data下的所有country节点for country in root.findall(\'country\'):
# 获取每一个country节点下rank节点的内容
rank = int(country.find(\'rank\').text)
if rank > 50:
# 删除指定country节点
root.remove(country)
############ 保存文件 ############tree.write("newnew.xml", encoding=\'utf-8\')
|
3、创建XML文档
创建方式(一)
|
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
|
from xml.etree import ElementTree as ET
# 创建根节点root = ET.Element("famliy")
# 创建节点大儿子son1 = ET.Element(\'son\', {\'name\': \'儿1\'})
# 创建小儿子son2 = ET.Element(\'son\', {"name": \'儿2\'})
# 在大儿子中创建两个孙子grandson1 = ET.Element(\'grandson\', {\'name\': \'儿11\'})
grandson2 = ET.Element(\'grandson\', {\'name\': \'儿12\'})
son1.append(grandson1)son1.append(grandson2)# 把儿子添加到根节点中root.append(son1)root.append(son1)tree = ET.ElementTree(root)
tree.write(\'oooo.xml\',encoding=\'utf-8\', short_empty_elements=False)
|
创建方式(一)
|
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
|
from xml.etree import ElementTree as ET
# 创建根节点root = ET.Element("famliy")
# 创建大儿子# son1 = ET.Element(\'son\', {\'name\': \'儿1\'})son1 = root.makeelement(\'son\', {\'name\': \'儿1\'})
# 创建小儿子# son2 = ET.Element(\'son\', {"name": \'儿2\'})son2 = root.makeelement(\'son\', {"name": \'儿2\'})
# 在大儿子中创建两个孙子# grandson1 = ET.Element(\'grandson\', {\'name\': \'儿11\'})grandson1 = son1.makeelement(\'grandson\', {\'name\': \'儿11\'})
# grandson2 = ET.Element(\'grandson\', {\'name\': \'儿12\'})grandson2 = son1.makeelement(\'grandson\', {\'name\': \'儿12\'})
son1.append(grandson1)son1.append(grandson2)# 把儿子添加到根节点中root.append(son1)root.append(son1)tree = ET.ElementTree(root)
tree.write(\'oooo.xml\',encoding=\'utf-8\', short_empty_elements=False)
|
创建方式(一)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
from xml.etree import ElementTree as ET
# 创建根节点root = ET.Element("famliy")
# 创建节点大儿子son1 = ET.SubElement(root, "son", attrib={\'name\': \'儿1\'})
# 创建小儿子son2 = ET.SubElement(root, "son", attrib={"name": "儿2"})
# 在大儿子中创建一个孙子grandson1 = ET.SubElement(son1, "age", attrib={\'name\': \'儿11\'})
grandson1.text = \'孙子\'
et = ET.ElementTree(root) #生成文档对象
et.write("test.xml", encoding="utf-8", xml_declaration=True, short_empty_elements=False)
|
由于原生保存的XML时默认无缩进,如果想要设置缩进的话, 需要修改保存方式:
|
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
|
from xml.etree import ElementTree as ET
from xml.dom import minidom
def prettify(elem):
"""将节点转换成字符串,并添加缩进。
"""
rough_string = ET.tostring(elem, \'utf-8\')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent="\t")
# 创建根节点root = ET.Element("famliy")
# 创建大儿子# son1 = ET.Element(\'son\', {\'name\': \'儿1\'})son1 = root.makeelement(\'son\', {\'name\': \'儿1\'})
# 创建小儿子# son2 = ET.Element(\'son\', {"name": \'儿2\'})son2 = root.makeelement(\'son\', {"name": \'儿2\'})
# 在大儿子中创建两个孙子# grandson1 = ET.Element(\'grandson\', {\'name\': \'儿11\'})grandson1 = son1.makeelement(\'grandson\', {\'name\': \'儿11\'})
# grandson2 = ET.Element(\'grandson\', {\'name\': \'儿12\'})grandson2 = son1.makeelement(\'grandson\', {\'name\': \'儿12\'})
son1.append(grandson1)son1.append(grandson2)# 把儿子添加到根节点中root.append(son1)root.append(son1)raw_str = prettify(root)
f = open("xxxoo.xml",\'w\',encoding=\'utf-8\')
f.write(raw_str)f.close() |
4、命名空间
详细介绍,猛击这里
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
from xml.etree import ElementTree as ET
ET.register_namespace(\'com\',"http://www.company.com") #some name
# build a tree structureroot = ET.Element("{http://www.company.com}STUFF")
body = ET.SubElement(root, "{http://www.company.com}MORE_STUFF", attrib={"{http://www.company.com}hhh": "123"})
body.text = "STUFF EVERYWHERE!"
# wrap it in an ElementTree instance, and save as XMLtree = ET.ElementTree(root)
tree.write("page.xml",
xml_declaration=True,
encoding=\'utf-8\',
method="xml")
|
PyYAML模块
Python也可以很容易的处理ymal文档格式,只不过需要安装一个模块,参考文档:http://pyyaml.org/wiki/PyYAMLDocumentation
configparser模块
configparser用于处理特定格式的文件如有键值对[]等,其本质上是利用open来操作文件。
|
1
2
3
4
5
6
7
8
9
|
# 注释1; 注释2
[section1] # 节点
k1 = v1 # 值
k2:v2 # 值
[section2] # 节点
k1 = v1 # 值
|
1、获取所有节点
|
1
2
3
4
5
6
|
import configparser
config = configparser.ConfigParser()
config.read(\'xxxooo\', encoding=\'utf-8\')
ret = config.sections()
print(ret)
|
2、获取指定节点下所有的键值对
|
1
2
3
4
5
6
|
import configparser
config = configparser.ConfigParser()
config.read(\'xxxooo\', encoding=\'utf-8\')
ret = config.items(\'section1\')
print(ret)
|
3、获取指定节点下所有的建
|
1
2
3
4
5
6
|
import configparser
config = configparser.ConfigParser()
config.read(\'xxxooo\', encoding=\'utf-8\')
ret = config.options(\'section1\')
print(ret)
|
4、获取指定节点下指定key的值
|
1
2
3
4
5
6
7
8
9
10
11
12
|
import configparser
config = configparser.ConfigParser()
config.read(\'xxxooo\', encoding=\'utf-8\')
v = config.get(\'section1\', \'k1\')
# v = config.getint(\'section1\', \'k1\')# v = config.getfloat(\'section1\', \'k1\')# v = config.getboolean(\'section1\', \'k1\') print(v)
|
5、检查、删除、添加节点
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import configparser
config = configparser.ConfigParser()
config.read(\'xxxooo\', encoding=\'utf-8\')
# 检查has_sec = config.has_section(\'section1\')
print(has_sec)
# 添加节点config.add_section("SEC_1")
config.write(open(\'xxxooo\', \'w\'))
# 删除节点config.remove_section("SEC_1")
config.write(open(\'xxxooo\', \'w\'))
|
6、检查、删除、设置指定组内的键值对
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import configparser
config = configparser.ConfigParser()
config.read(\'xxxooo\', encoding=\'utf-8\')
# 检查has_opt = config.has_option(\'section1\', \'k1\')
print(has_opt)
# 删除config.remove_option(\'section1\', \'k1\')
config.write(open(\'xxxooo\', \'w\'))
# 设置config.set(\'section1\', \'k10\', "123")
config.write(open(\'xxxooo\', \'w\'))
|
shutil模块
高级的 文件、文件夹、压缩包 处理模块,注意当前用户要是对其他文件或目录没有权限会报错
shutil.copyfileobj(fsrc, fdst[, length]) 将文件内容拷贝到另一个文件中
|
1
2
3
|
import shutil
shutil.copyfileobj(open(\'/etc/passwd\',\'r\'), open(\'password\', \'w\'))
|
shutil.copyfile(src, dst) 拷贝文件
|
1
2
3
|
import shutil
shutil.copyfile(\'/etc/passwd\',\'password1\')
|
shutil.ignore_patterns(*patterns) 忽略某些文件
shutil.copytree(src, dst, symlinks=False, ignore=None) 递归的去拷贝文件夹
|
1
2
3
|
import shutil
shutil.copytree(\'/etc\',\'etc\', ignore=shutil.ignore_patterns(\'*.conf\', \'tmp*\'))
|
shutil.rmtree(path[, ignore_errors[, onerror]]) 递归删除文件夹
|
1
2
3
|
import shutil
shutil.rmtree(\'etc\')
|
shutil.move(src, dst) 它类似mv命令,其实就是重命名。
|
1
2
3
|
import shutil
shutil.move(\'folder1\', \'folder3\')
|
shutil.make_archive(base_name, format,...) 创建压缩包并返回文件路径,例如:zip、tar
创建压缩包并返回文件路径,例如:zip、tar
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/ - format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
|
1
2
3
4
5
6
7
|
import shutil
#将 /home/tomcat/ 下的文件打包放置当前程序目录ret = shutil.make_archive("test", \'gztar\', root_dir=\'/home/tomcat/\')
#将 /home/tomcat/ 下的文件打包放置 /home/tomcat/目录ret = shutil.make_archive("/home/tomcat/www", \'gztar\', root_dir=\'/home/tomcat/\')
|
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
import zipfile
# 压缩z = zipfile.ZipFile(\'laxi.zip\', \'w\')
z.write(\'a.log\')
z.write(\'data.data\')
z.close()# 解压z = zipfile.ZipFile(\'laxi.zip\', \'r\')
z.extractall()z.close() |
TarFile
|
1
2
3
4
5
6
7
8
9
10
11
12
|
import tarfile
# 压缩tar = tarfile.open(\'your.tar\',\'w\')
tar.add(\'/Users/wupeiqi/PycharmProjects/bbs2.log\', arcname=\'bbs2.log\')
tar.add(\'/Users/wupeiqi/PycharmProjects/cmdb.log\', arcname=\'cmdb.log\')
tar.close()# 解压tar = tarfile.open(\'your.tar\',\'r\')
tar.extractall() # 可设置解压地址
tar.close() |