欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python day 9: xlm模块,configparser模块,subprocess模块

程序员文章站 2022-07-02 12:48:07
python day 9 2019/10/12 学习资料来自老男孩教育 [TOC] 1. xml模块 xml模块是在json没有出来之前,用于不同语言之间通信,交换,处理xml格式数据的一种方式。 1.1 初识xml 1.2 遍历xml文档的指定节点 创建一个xml文档,写入如下内容: 读取xml文 ......

目录

python day 9

2019/10/12

学习资料来自老男孩教育

1. xml模块

xml模块是在json没有出来之前,用于不同语言之间通信,交换,处理xml格式数据的一种方式。

1.1 初识xml

import requests

from xml.etree import elementtree as et

# 使用第三方模块requests发送http请求,或者xml格式内容
response = requests.get('http://www.webxml.com.cn//webservices/qqonlinewebservice.asmx/qqcheckonline?qqcode=375132083')
result = response.text  # 字符串类型

# 使用xml包中的elementtree解析xml格式内容
# xml接收一个字符串作为参数,将其格式化特殊的对象
node = et.xml(result)

#获取内容
if node.text =='y':
    print('在线')
import requests

response2 = requests.get('http://www.webxml.com.cn/webservices/traintimewebservice.asmx/getdetailinfobytraincode?traincode=k234&userid=starpinlan')
result2 = response2.text  #字符串str

from xml.etree import elementtree as et

root = et.xml(result2)  #<class 'xml.etree.elementtree.element'>
# print(type(node2))

for node in root.iter('traindetailinfo'):  #iter方法是找到root这个对象中的后代标签名是traindetailinfo的所有元素
    print(node.tag,node.attrib)  #输出它的标签名,以及它的属性
    print(node.find('trainstation').text) #find方法是找到指定名称的第一个子标签

1.2 遍历xml文档的指定节点

  • 创建一个xml文档,写入如下内容:
s1 = '''
<data>
    <country name="liechtenstein">
        <rank updated="yes">2</rank>
        <year id="year">2024</year>
        <gdppc>141100</gdppc>
        <neighbor direction="e" name="austria" />
        <neighbor direction="w" name="switzerland" />
    </country>
    <country name="singapore">
        <rank updated="yes">5</rank>
        <year id="year">2027</year>
        <gdppc>59900</gdppc>
        <neighbor direction="n" name="malaysia" />
    </country>
    <country name="panama">
        <rank updated="yes">69</rank>
        <year id="year">2027</year>
        <gdppc>13600</gdppc>
        <neighbor direction="w" name="costa rica" />
        <neighbor direction="e" name="colombia" />
    </country>
</data>
'''

with open('xmltest.xml','w+',encoding='utf-8') as f:
    f.write(s1)
    f.flush()
  • 读取xml文档,不修改原文件
from xml.etree import elementtree as et
#使用xml格式化字符串
root = et.xml(open('xmltest.xml',encoding='utf-8').read())  #此种方式只能读取,不可修改文件
print(root.tag)
for node in root.iter('country'):
    print(node.tag,node.attrib,node.find('year').text)
    child_node = node.find('year')  #找到标签名为year的所有节点
    new_year = int(child_node.text)+1 #将year标签的值加1
    child_node.text = str(new_year)
    child_node.set('name','year')  #设置属性name,其值为year
    # del child_node.attrib['name']  #删除name属性键值对

#保存文件需要另创建一个新文件
tree = et.elementtree(root)  #创建一个内容为root的elementtree对象
tree.write('newxml.xml',encoding='utf-8')  #一定要通过write写入文件。
  • 使用parse方法解析文件,可以修改原文件。
#使用elementtree的parse方法解析文件

from xml.etree import elementtree as et

tree = et.parse('xmltest.xml')  #parse方法可以打开文件,并解析其内容
# print(tree,type(tree))  # <class 'xml.etree.elementtree.elementtree'>
root = tree.getroot()   # getroot方法获得最顶层的根节点
# print(root.tag)  # data

for node in root.iter('year'):
    print(node.tag,node.text)
    new_year = int(node.text) + 1
    node.text = str(new_year)
    node.set('id','year')  # 设置id属性,其值为year,
    print(node.attrib)    #  attrib是字典形式

tree.write('xmltest.xml')  #parse可以直接修改原文件
  • 查看一个节点都有哪些方法
from xml.etree  import elementtree as et

tree = et.parse('xmltest.xml')
root = tree.getroot()
print(dir(root))  #查看节点都有哪些方法

'''
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__delitem__', '__dir__', '__doc__', 
 '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', 
 '__hash__', '__init__', '__init_subclass__', '__le__', '__len__', '__lt__', '__ne__', '__new__', 
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__setstate__', '__sizeof__', 
 '__str__', '__subclasshook__', 'append', 'attrib', 'clear', 'extend', 'find', 'findall', 'findtext', 
 'get', 'getchildren', 'getiterator', 'insert', 'items', 'iter', 'iterfind', 'itertext', 'keys', 'makeelement', 
 'remove', 'set', 'tag', 'tail', 'text']
 #常用tag,attrib,find,text,set,iter,get,append,clear,extend,findall,getchildren,insert,makeelement
 '''

1.3 通过python手工创建xml文档

from xml.etree import elementtree as et

root = et.element('namelist')  #通过element类创建一个名为namelist的xml元素(对象)
print(root,type(root))  # <element 'namelist' at 0x00000184ad6c21d8> <class 'xml.etree.elementtree.element'>
name1 = et.subelement(root,'name',attrib={'enrolled':'yes'})  # 给root创建子节点,子节点的标签名是name,属性
name1.text = 'lanxing'  #给内容赋值
age1 = et.subelement(name1,'age',attrib={'checked':'no'})  # 给name1创建子节点
age1.text = '18'
sex1 = et.subelement(name1,'sex',attrib={'sex':'male'})
sex1.text = 'male'

name2 = et.subelement(root,'name',attrib={'enrolled':'yes'})  # 给root创建子节点,子节点的标签名是name,属性
name2.text = '蓝星'  #给内容赋值
age2 = et.subelement(name2,'age',attrib={'checked':'no'})  # 给name1创建子节点
age2.text = '28'  # 必须是字符串才可以序列化
sex2 = et.subelement(name2,'sex',attrib={'sex':'male'})
sex2.text = 'female'

tree = et.elementtree(root)  # 通过elementtree类生成文档对象
tree.write('xmltest2.xml',encoding='utf-8',xml_declaration=true)  #将文档对象写入文件,declaration表示声明文件,相当于注释。

1.4 创建节点的两种方式

from xml.etree import elementtree as et

tree = et.parse('xmltest.xml')

root = tree.getroot()
# 创建新节点的第一种方式:makeelement
son = root.makeelement('son',{'sex':'male'})
print(son,type(son))  # <element 'son' at 0x000002e1e1b10138> <class 'xml.etree.elementtree.element'>
# 创建新节点的第二种方式:通过element类进行创建,实际第一种方式也是调用element类
son2 = et.element('son2',{'sex':'male'})
son2.text = '男'
# 将新节点添加到root上
root.append(son)
root.append(son2)

tree.write('xmltest.xml',encoding='utf-8',short_empty_elements=false) # short参数是控制是否可简写的。

1.5 总结

xml:
    1,解析:
            str:elementtree.xml(str)
            文件:elementtree.parse(file)
    2,element对象操作:
            tag,text,find,iter,get,set,findall,append,insert,remove。
    3,重新写入文件:
            elementtree(element(tag,attrib)).write(filepath,encoding=none)
            必须是elementtree对象才有写入方法。
    4,创建xml:
            root= element(tag,attrib)
            ele = root.makeelement(tag,attrib)
            root.append(ele)
            elementtree.subelement(root,tag,attrib)
    5,缩进
            from xml.dom import minidom

            def prettify(root):
                '''将节点转换成字符串,并添加缩进'''
                rough_string = et.tostring(root,'utf-8')
                reparsed = minidom.parsestring(rough_string)

                return reparsed.topprettyxml(indent='\t')
    6,命名空间
    7,非常重要
            一切皆对象,type(obj)查看对象的类。dir(obj)查看对象具有的方法。

2. configparser模块

configparser模块用来处理配置文件,配置文件是以.ini结尾的文件,长得像下面这样。

[autoupdate] #[xxx]叫做节点
configfileurl = # 键值对,左边的叫key,右边的叫value
autoupdatecheckdelay = 30
configfilekey1 = edad921681272c3e37f34020450a6963
configfilekey2 = 132150629469920000
lstm_autoupdate = 1570589347
isautoupdate = 0

[packageinstallinfo]
default = 2
c6aa1078e4d92ff0573452220ca2d8ae = 4

import configparser

con = configparser.configparser()  # 创建一个configparser对象
con.read('config.ini',encoding='utf-8') # 打开文件并读取文件内容,放进内存

# 1,获取所有节点
# con对象的sections方法,内存中寻找所有的[xxx],一个[xxx]就是一个配置文件的节点
ret = con.sections() # 获取所有的节点名称,并返回一个列表
print(ret)  # ['autoupdate', 'packageinstallinfo']

# 2,获取指定节点下所有的键值对,将key与值作为元组,元组作为列表的元素返回。
ret2 = con.items('autoupdate')
print(ret2)  # [('configfileurl', 'https://update.pan.baidu.com/autoupdate'), ('isautoupdate', '0'), ('autoupdatecheckdelay', '30'), ('configfilekey1', 'edad921681272c3e37f34020450a6963'), ('configfilekey2', '132150629469920000'), ('lstm_autoupdate', '1570589347')]

# 3,获取指定节点所有的键
ret3 = con.options('packageinstallinfo')
print(ret3)  # ['default', 'c6aa1078e4d92ff0573452220ca2d8ae']

# 4, 获取指定节点下指定key的值,get(sections,key)
value1 = con.get('packageinstallinfo','default')  #默认返回字符串
print(value1,type(value1))
# 可以使用getint方法,自动将字符串转换为整数返回
value2 = con.getint('packageinstallinfo','default')
print(value2,type(value2))
# 可以使用getfloat方法,自动将字符串转换为浮点数返回
value3 = con.getfloat('packageinstallinfo','default')
print(value3,type(value3))
# 如果值是布尔值,可以使用getboolean方法,自动将字符串转换为布尔值返回
# value4 = con.getboolean('packageinstallinfo','default')  # 会报错,因为其值不是布尔值

# 5,检查,添加,删除节点

has_sec = con.has_section('autoupdate')  #判断是否有节点,如果有返回true
print(has_sec)

con.add_section('name')

con.remove_section('name')

# 添加,删除操作必须重新写入文件,否则不能持久化保存。


# 6,检查,删除,设置指定节点内的键值对

#检查
has_opt =con.has_option('autoupdate','isautoupdate')

#删除
con.remove_option('autoupdate','isautoupdate')

#设置
con.set('autoupdate','isautoupdate','0')

con.write(open('config.ini','w'))  #write写入得接收一个文件对象

4. shutil模块

shutil模块是高级的文件,文件夹,压缩包处理模块。

import shutil
# 将文件内容复制到另一个文件中
# shutil.copyfileobj(fsrc,fdst[,length]) 将一个文件流对象复制给另一个文件流对象,长度是可选的。
f1 =open('1.txt','r',encoding='utf-8')
f2 =open('2.txt','w',encoding='utf-8')
shutil.copyfileobj(f1,f2)
f1.close()
f2.close()

# shutil.copyfile(src,dst),复制文件
shutil.copyfile('1.txt','3.txt')

# shutil.copymode(src,dst) 仅复制文件的权限,用户,组和内容都不变
shutil.copymode('1.txt','2.txt')  #dst要存在
# shutil.copystat(src,dst) 仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copystat('1.txt', '2.txt')
# shutil.copy(src,dst) #复制文件和权限
shutil.copy('1.txt','2.txt')
# shutil.copy2(src,dst) # 复制文件和状态信息
shutil.copy2('1.txt','2.txt')
# shutil.ignore_patterns(*patterns)忽略某些格式的文件
# shutil.copytree(src, dst, symlinks=false, ignore=none) 递归地去复制文件夹
shutil.copytree('.','../day10',symlinks=true,ignore=shutil.ignore_patterns('*.py'))

# shutil.rmtree(path[, ignore_errors[, onerror]])
shutil.rmtree('../day10')# 递归的去删除文件
# shutil.move(src, dst) 递归的去移动文件,它类似mv命令,其实就是重命名。
shutil.make_archive(base_name, format[,root_dir[,owner[,group[,logger]]]])
# 创建压缩包并返回文件路径,
# 其中base_name是指压缩包的文件包,也可以压缩包的路径。
# format:压缩包种类,zip,tar,bztar,gztar.
# root_dir: 要压缩的文件夹路径(默认当前目录)
# owner:用户,默认当前用户
# group:组,默认当前组
# logger:用于记录日志,通常是logging.logger对象
shutil.make_archive('../test1','tar','.')

shutil 对压缩包的处理是调用 zipfile 和 tarfile 两个模块来进行的,

import zipfile

# 压缩
z = zipfile.zipfile('laxi.zip', 'w') #创建一个zip的压缩包对象
z.write('a.log') # 往压缩包里面加入文件
z.write('data.data')
z.close()

# 解压
z = zipfile.zipfile('laxi.zip', 'r')
z.extractall() # 解压所有文件
print(z.namelist())  # 获得压缩包内的所有文件名
z.extract('1.txt') # 单独解压指定文件
z.close()


import tarfile

# 压缩
tar = tarfile.open('your.tar','w')  # 创建tar格式的压缩包
tar.add('/users/wupeiqi/pycharmprojects/bbs2.log', arcname='bbs2.log')  #往里面加入压缩文件,可以另外设置名字为bbs2.log
tar.add('/users/wupeiqi/pycharmprojects/cmdb.log', arcname='cmdb.log')
tar.close()

# 解压
tar = tarfile.open('your.tar','r')
tar.extractall()  # 可设置解压地址
print(tar.getmembers())  #返回压缩包内的所有文件名
tar.extractfile('1.txt')  #单独解压指定文件
tar.close()

5. subprocess模块

专门用于python执行系统命令

import subprocess

ret = subprocess.call('ipconfig')  # call执行系统命令,返回状态码
print(ret)  # 成功的返回码是0

ret2 = subprocess.check_call('ipconfig')  # 执行命令,返回状态码
print(ret2)
ret3 = subprocess.check_output('ipconfig')  # 执行命令,返回字节类型的命令结果
print(ret3)

'''
popen()用于执行复杂的系统命令

参数:
    args:shell命令,可以是字符串或者序列类型(如:list,元组)
    bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
    stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
    preexec_fn:只在unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
    close_sfs:在windows平台下,如果close_fds被设置为true,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
    所以不能将close_fds设置为true同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
    shell:同上
    cwd:用于设置子进程的当前目录
    env:用于指定子进程的环境变量。如果env = none,子进程的环境变量将从父进程中继承。
    universal_newlines:不同系统的换行符不同,true -> 同意使用 \n
    startupinfo与createionflags只在windows下有效
    将被传递给底层的createprocess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等 
'''

subprocess.popen('mkdir test',shell=true,cwd='.')  # shell是true的情况下,就是将前面的字符串当作命令来输入
subprocess.popen(['ipconfig','dir'])  # 执行多个命令

obj = subprocess.popen(["python"], stdin=subprocess.pipe, stdout=subprocess.pipe, stderr=subprocess.pipe, universal_newlines=true)
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")
obj.stdin.close()

cmd_out = obj.stdout.read()
obj.stdout.close()
cmd_error = obj.stderr.read()
obj.stderr.close()

print(cmd_out)
print(cmd_error)