1.文件操作
- 字符串类型(str),在程序中用于表示文字信息,本质上是unicode编码中的二进制。
name ="武沛齐"
- 字节类型(bytes)
可表示文字信息,本质上是utf-8/gbk等编码的二进制(对unicode进行压缩,方便文件存储和网络传输。)
name="武沛齐"
data = name.encode('utf-8')
print(data) #b'\xe6\xad\xa6\xe6\xb2\x9b\xe9\xbd\x90'
result = data.decode('utf-8')
print(result) # "武沛齐"
可表示原始二进制(图片、文件等信息)
1.1读文件
- 读文本文件
# 1.打开文件
# 路径
# 相对路径:'info.txt',当前程序到底是在哪里运行的
# 绝对路径:'/Users/wupeigi/PycharmProjects/luffyCourse/day09/info.txt'
# 模式
# rb,表示读取文件原始的二进制(r,读read;b,二进制binary;)
# 1.打开文件
file_object = open('info.txt',mode='rb')
# 2.读取文件内容,并赋值给data
data = file_object.read()
# 3.关闭文件
file_object.close()
print(data) # 结果为二进制类型
# 字节类型转换为字符串类型
text = data.decode('utf-8')
print(text)
# 1.打开文件
# 模式
# rt,表示读取文件原始的二进制转化为字符串类型
file_object = open('info.txt',mode='rt', encoding = 'utf-8')
# 2.读取文件内容,并赋值给data
data = file_object.read()
# 3.关闭文件
file_object.close()
print(data) # 结果为字符串类型
注意事项:读文件时,如果文件不存在,程序会报错
# 判断路径是否存在?
import os
file_path = 'F:/BaiduSyncdisk/Python/info.txt'
exists = os.path.exists(file_path)
print(exists)
if exists:
# 打开文件
file_object = open('info.txt', mode='rt', encoding='utf-8')
# 2.读取文件内容,并赋值给data
data = file_object.read()
# 3.关闭文件
file_object.close()
print(data) # 结果为字符串类型
else:
print('文件不存在')
- 读图片等非文本内容文件
file_object= open('al.png',mode='rb')
data = file_object.read()
file_object.close()
print(data) # 结果为二进制
1.2写文件
- 写文本文件
# 打开文件
# 路径:t1.txt
# 模式:wb(要求写入内容需要是字节类型)
file_object = open('t1.txt',mode='wb',)
# 2.写入内容
data = file_object.write('wupwiqi'.encode('utf-8'))
# 3.关闭文件
file_object.close()
file_object = open('t2.txt',mode='wt', encoding = 'utf-8')
data = file_object.write('wupwiqi')
file_object.close()
- 写图片等格式
# 读图,格式rb
f1 = open('0.电子签名.png', mode='rb')
content = f1.read()
f1.close()
# 写图,a1.png,格式wb
f2 = open('a1.png', mode='wb')
f2.write(content)
f2.close()
基础案例:
# 案例1,用户注册
user = input('请输入用户名:')
pwd = input('请输入密码:')
# 账号、密码拼接
data = '{}-{}'.format(user,pwd)
file_object = open('files/info.txt', mode='wt', encoding='utf-8')
file_object.write(data)
file_object.close()
# 案例2:多用户注册.
# w写入文件,会先清空文件,再在文件中写入内容
file_object = open('files/info.txt', mode='wt', encoding='utf-8')
while True:
user = input('请输入用户名:')
if user.upper() == 'Q':
break
pwd = input('请输入密码:')
data = '{}-{}\n'.format(user,pwd)
file_object.write(data)
file_object.close()
小高级案例:
利用Python向某个网址发送请求并获取结果(利用第三方模块)
- 下载第三方模块
pip install requests
/Library/Frameworks/Python. framework/Versions/3.9/bin/pip3 install requests
- 使用第三方模块
import requests
# 案例3:去网上下载一点文本,文本信息写入文件
import requests
res = requests.get(
url="https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=20",
# 添加伪造请求头,让网址认为是人在访问
headers={
"User-Agent": "Mozilla/5.0(Macintosh;Intel Mac os x 10_15_7)AppleWebKit/537.36(KHTML,like Gecko)Chrome/87.0.4280.88 Safari/537.36"
}
)
# print(res.content)
# 网络传输的原始二进制信息(bytes)
# 读取到的信息写入文件log1.txt
file_object = open('files/logl.txt', mode='wb')
file_object.write(res.content)
file_object.close()
# 案例4:去网上下载一张图片,图片写入本地文件
import requests
res = requests.get(
url="https://hbimg.huabanimg.com/c7e1461e4b15735fbe625c4dc85bd19904d96daf6de9fb-tosv1r_fw1200",
# 添加伪造请求头,让网址认为是人在访问
headers={
"User-Agent": "Mozilla/5.0(Macintosh;Intel Mac os x 10_15_7)AppleWebKit/537.36(KHTML,like Gecko)Chrome/87.0.4280.88 Safari/537.36"
}
)
# 网络传输的原始二进制信息(bytes)
file_object = open('files/美女.png', mode='wb')
file_object.write(res.content)
file_object.close()
- 注意事项:
路径:绝对路径/相对路径
文件不存在时:w模式会新建然后再写入内容;文件存在时,w模式会清空文件再写入内容。
1.3文件打开模式
上文我们基于文件操作基本实现了读、写的功能,其中涉及的文件操作模式:rt,rb,wt,wb,其实在文件操作中还有其他的很多模式。
关于文件的打开模式常见应用有:
- 只读:r、rt,rb(用)
存在,读
不存在,报错
- 只写:w、wt、wb(用)
存在,清空再写
不存在,创建再写
- 只写:x、xt、xb(不常用)
存在,报错
不存在,创建再写。
- 只写:a、at、ab【尾部追加】(用)
存在,尾部追加。
不存在,创建再写。
读写
- r+、rt+、rb+,默认光标位置:起始位置
# info.txt = 'alex-123'
file_object = open('info.txt', mode='rt+', encoding='utf-8')
# 读取内容
data = file_object.read()
print(data)
# 写入内容
file_object.write('你好呀')
file_object.close()
file_object = open ('info.txt', mode='rt+', encoding='utf-8')
# 写入内容
file_object.write('alex')
# 读取内容
data = file_object.read()
print(data) #-123
file_object.close()
- w+、wt+、wb+,默认光标位置:起始位置(清空文件)
# info.txt = 'alex-123'
file_object = open ('info.txt', mode='wt+', encoding='utf-8')
# 读取内容
data = file_object.read()
print(data) # 内容为空
# 写入内容
file_object.write('你好呀')
# 将光标位置重置起始
file_object.seek(0)
# 读取内容
data = file_object.read()
print(data) # 你好呀
file_object.close()
- x+、xb+,默认光标位置:起始位置(新文件)
- a+、ab+,默认光标位置:末尾
# info.txt = 'alex-123'
file_object = open ('info.txt', mode='at+', encoding='utf-8')
# 写入内容
file_object.write('你好呀')
# 将光标位置重置起始
file_object.seek(0)
# 读取内容
data = file_object.read()
print(data) # alex-123你好呀
file_object.close()
多用户注册案例:
# 打开文件
file_object = open('files/account.txt', mode='a')
# 写入用户名-密码
while True:
user = input('请输入用户名:')
if user.upper() == 'Q':
break
pwd = input('请输入密码:')
data = '{}-{}\n'.format(user,pwd)
file_object.write(data)
file_object.flush() # 立即将写入数据刷到硬盘
# 关闭文件
file_object.close()
1.4常见功能
- read,读
读所有(常用)
f = open('info.txt', mode='r', encoding='utf-8')
data = f.read()
f.close()
f = open('info.txt', mode='rb')
data = f.read()
f.close()
读n个字符(字节)(会用到)
# info.txt = 武沛齐'
f = open('info.txt', mode='r', encoding='utf-8')
# 读1个字符
data = f.read(1)
f.close()
print(data) # 武
f = open('info.txt', mode='rb')
# 读1个字节
data = f.read(1) # b'\xe6\xad\xa6' <class 'bytes'>
f.close()
- readline,读一行
f = open('info.txt', mode='r', encoding='utf-8')
# 读第一行
v1 = f.readline()
print(v1)
# 继续读下一行
v2 = f.readline()
print(v2)
f.close()
- readlines,读所有行,每行作为列表的一个元素
f = open('info.txt', mode='r', encoding='utf-8')
data_list = f.readlines()
f.close()
print(data_list)
- 循环,读大文件(常用)
f = open('info.txt', mode='r', encoding='utf-8')
for line in f:
print(line.strip()) # strip()去除line中的空格、换行
f.close()
- write,写
f = open('info.txt', mode='a',encoding='utf-8')|
f.write("武沛齐")
f.close()
f = open('info.txt',mode='ab')
f.write("武沛齐".encode("utf-8"))
f.close()
- flush,刷到硬盘
f = open('info.txt', mode='a',encoding='utf-8')
while True:
# write不是写到了硬盘,而是写在缓冲区,系统会将缓冲区的内容刷到硬盘。
f.write("武沛齐")
f.flush() # 立即将写入数据刷到硬盘
f.close()
- 移动光标位置(字节)
f = open('info.txt', mode='r+',encoding='utf-8')
# 移动光标位置,在次光标之后开始写内容(如有原内容,则会覆盖)
f.seek(3) # 移动到制定‘字节’,seek()对a模式无用,三个字节一个字符
f.write("武沛齐")
f.close()
注意:在a模式下,调用write在文件中写入内容时,永远只能将内容写入到尾部,不会写到光标的位置。
- 获取当前光标位置
f = open('info.txt', mode='r',encoding='utf-8')
f.read(3) # 3个字符,3*3=9个字节
f.read(1) # 1个字符,9+3*1=12个字节
position = f.tell() # 获取当前光标位置
f.close()
print(position) # 12
1.5上下文管理
之前对文件进行操作时,每次都要打开和关闭文件,比较繁琐且容易忘记关闭文件。
以后再进行文件操作时,推荐大家使用with上下文管理,它可以自动实现关闭文件。
with open('XXX.txt', mode='rb') as file_object:
data = file_object.read()
print(data)
在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:
with open('XXX.txt', mode='rb') as f1, open('XXX.txt', mode='rb') as f2:
pass
练习题
1.补充代码:实现下载视频并保存到本地
import requests
res = requests.get(
url="https://www.bilibili.com/video/BV1qh411273b?p=127&spm_id_from=pageDriver",
headers={
"User-Agent": "Mozilla/5.0(Macintosh;Intel Mac os x 10_15_7)AppleWebKit/537.36(KHTML,like Gecko)Chrome/87.0.4280.88 Safari/537.36"
}
)
# 视频的文件内容
with open('123.mp4', mode='wb') as file_object:
file_object.write(res.content)
2.日志计数,计算某用户223.73.89.192访问次数。日志文件如下files/access.log
total_count = 0
ip = '223.73.89.192'
# 打开日志文件
with open('files/access.log', mode='r', encoding='utf-8') as file_object:
# 循环日志文件每一行
for line in file_object:
# 每行前端不是ip,继续循环
if not line.startswith(ip):
continue
total_count += 1
print(total_count)
3.日志计数升级版,找到所用用户访问次数
user_dict = {}
# 打开日志文件
with open('files/access.log', mode='r', encoding='utf-8') as file_object:
# 循环日志文件每一行
for line in file_object:
# 通过'空格'进行分割,取第0个元素,为用户ip
user_ip = line.split(" ")[0]
# 判断用户ip是否在字典user_dict中,如果存在,值加1
if user_ip in user_dict:
user_dict[user_ip] += 1
# 以user_ip为键,让第一次找到本ip的值等于1
else:
user_dict[user_ip] = 1
print(user_dict)
4.筛选出股票 当前价大于20的所有股票数据。原文件如下stock.txt
with open('files/stock.txt', mode='r', encoding='utf-8') as file_object:
# 跳过第一行,表头
file_object.readline()
# 接着往下读
for line in file_object:
text = line.split(',')[2] # 用split()对读到的line用','分割,取第2个值
price = float(text)
if price > 20:
print(line.strip()) # 用strip()去掉line()自带的换行符
5.根据要求修改文件的内容,原文件内容如下:ha.conf
请将文件中的luffycity修改为pythonav
思路:
- 文件读到内存,在再通过replace(适用于小文件,不适用于大文件)
- 挨个位置读文件的内容,遇到luffycity将其替换成pythonav(不可取,替换字符长度不一样)
- 同时打开两个文件,边读边写(适用于大小文件)
# 同时打开两个文件ha.conf和new.congf
with open('files/ha.conf', mode='r', encoding='utf-8') as read_file_object, open('files/new.conf', mode='w', encoding='utf-8') as write_file_object:
for line in read_file_object:
new_line = line.replace('luffycity', 'pythonav')
write_file_object.write(new_line)
# 重命名
import shutil
shutil.move('files/new.conf', 'files/ha.conf')
2.csv格式文件
逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。
对于这种格式的数据,我们需要利用open函数来读取文件并根据逗号分隔的特点来进行处理。
案例:下载文档中的所有图片且以用户名为图片名称存储。文件如下mv.csv
import os
import requests
# 打开mv.csv文件
with open('files/mv.csv', mode='r', encoding='utf-8') as file_object:
# 跳过第一行,表头
file_object.read()
# 接着往下读
for line in file_object:
# 用strip()去掉line()自带的空白/换行符,用split()对读到的line用','分割
# 用三个值分别接收ID、用户名、头像
user_id, username, url = line.strip().split(',')
print(username,url)
# 1.根据url下载图片
res = requests.get(
url=url,
headers={
"User-Agent": "Mozilla/5.0(Macintosh;Intel Mac os x 10_15_7)AppleWebKit/537.36(KHTML,like Gecko)Chrome/87.0.4280.88 Safari/537.36"
}
)
res.content # 图片文件的内容
# 检查images目录是否存在?不存在则创建images目录
if not os.path.exists('images'):
os.makedirs('images')
# 2.将图片的内容写入到文件
with open('images/{}.png'.format(username), mode='wb') as img_object:
img_object.write(res.content)
3.ini格式文件
ini文件是Initialization File的缩写,平时用于存储软件的的配置文件。例如:MySQL数据库的配置文件my.ini。
这种格式是可以直接使用open来出来,考虑到自己处理比较麻烦,所以Python为我们提供了更为方便的方式。
- 读取所有节点
import configparser config = configparser.ConfigParser() # config.read('/Users/wupeigi/PycharmProjects/luffyCourse/day09/files/my.conf', encoding='utf-8') # 绝对路径 config.read('my.conf', encoding='utf-8') # 相对路径 # 读取所有节点 result = config.sections() print(result) # ['mysgld','mysqld_safe','client']
- 读取节点下的键值
# 读取节点下的键值 result = config.items('musqld_safe') print(result) # [('log-error', '/var/log/mariadb/mariadb.log'), ('pid-file', '/var/run/mariadb/mariadb.pid')] for key,value in config.items('musqld_safe') print(key, value) # log-error /var/log/mariadb/mariadb.log # pid-file /var/run/mariadb/mariadb.pid
- 获取某个节点下的键对应的值
# 获取某个节点下的键对应的值 result = config.get('musqld', 'collation-server') print(result) # utf8_general_ci
- 其他功能
# 1.是否存在节点'client' v1 = config.has_section('client') print(v1) # 2.添加一个节点'group' config.add_section('group') # 当前只是添加到内存,并未写入到文件 # 在节点group下添加键值name = wupeiqi config.set('group', 'name', 'wupeiqi') #写入到文件files/new.ini config.write(open('files/new.ini', mode='w', encoding='utf-8')) # 3.删除 # 删除节点client config.remove_section('client') # 删除节点mysqld下的datadir键值 config.remove_option('mysqld', 'datadir') # 写入新文件new.ini中 config.write(open('files/new.ini', mode='w', encoding='utf-8'))
4.XML格式文件
可扩展标记语言,是一种简单的数据存储语言,XML被设计用来传输和存储数据。
- 存储,可用来存放配置文件,例如:java的配置文件。
- 传输,网络传输时以这种格式存在,例如:早期ajax传输的数据、soap协议等。
注意:在Python开发中用的相对来比较少,大家作为了解即可(后期课程在讲解微信支付、微信公众号消息处理时会用到基于xml传输数)
4.1读取文件和内容
from xml.etree import ElementTree as ET # 用ET代指ElementTree
# ET直接打开xo.xm1文件
tree = ET.parse("xo.xml")
# 获取根标签'data'
root = tree.getroot()
print(root) # <Element 'data' at 0x000002393D0A3D60>
from xml.etree import ElementTree as ET
content = """
<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="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>
"""
# 获取根标签'data'
root = ET.XML(content)
print(root) # <Element 'data' at 0x0000024C61227810>
4.2读取节点数据
from xml.etree import ElementTree as ET
content = """
<data>
<country name="Liechtenstein">
<rank>2</rank>
<year>2023</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="w" name="Switzerland" />
</country>
<country name="Panama">
<rank>69</rank>
<year>2026</year>
<gdppc>13600</gdppc>
<neighbor direction="w" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>
"""
# 1.获取根标签'data'
root = ET.XML(content)
print(root) # <Element 'data' at 0x0000014349527720>
# 2.获取根标签的子标签
for child in root:
# child.tag = country
# child.attrib = {'name':'Liechtenstein'}...# 获取标签属性
print(child.tag, child.attrib)
# country {'name': 'Liechtenstein'}
# country {'name': 'Panama'}
for node in child:
# node.tag = rank, node.attrib = {}, node.text = 2
print(node.tag, node.attrib, node.text)
# 2.另一方法
root = ET.XML(content)
country_object = root.find('country')
print(country_object.tag, country_object.attrib) # country {'name': 'Liechtenstein'}
# 3.从根标签data中找到所有‘year’标签,输出标签,值
root = ET.XML(content)
for child in root.iter('year'):
print(child.tag, child.text)
# year 2023
# year 2026
# 3.另一种方法
root = ET.XML(content)
# 找到所有country标签
v1 = root.findall('country')
print(v1) # [<Element 'country' at 0x000001C39EE33D60>, <Element 'country' at 0x000001C39EE33F40>]
# 找到第一个country标签下的rank标签
v2 = root.find('country').find('rank') # 将标签rank中的值赋值给v2
print(v2.text) # 2
4.3修改和删除节点
from xml.etree import ElementTree as ET
content = """
<data>
<country name="Liechtenstein">
<rank>2</rank>
<year>2023</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="w" name="Switzerland" />
</country>
<country name="Panama">
<rank>69</rank>
<year>2026</year>
<gdppc>13600</gdppc>
<neighbor direction="w" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>
"""
# 获取根标签'data'
root = ET.XML(content)
# 1.修改节点内容和属性
# 找到第一个country标签中的rank标签
rank = root.find('country').find('rank')
print(rank.text) # 2
rank.text = "999" # 修改rank的文本为999
rank.set('update','2020-11-11') # 给rank增加属性update="2020-11-11"
print(rank.text,rank.attrib) # 999 {'update': '2020-11-11'}
# 保存文件,把最新内容写入文件new.xml中
tree = ET.ElementTree(root)
tree.write("new.xml",encoding='utf-8')
"""
<data>
<country name="Liechtenstein">
<rank update="2020-11-11">999</rank>
<year>2023</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="w" name="Switzerland" />
</country>
<country name="Panama">
<rank>69</rank>
<year>2026</year>
<gdppc>13600</gdppc>
<neighbor direction="w" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>
"""
# 2.删除节点
root.remove(root.find("country'))
print(root.findall('country')) # [<Element 'country' at 0x00000269C5813EA0>]
# 保存文件,把最新内容写入文件newnew.xml中
tree = ET.ElementTree(root)
tree.write("newnew.xml",encoding='utf-8')
"""
<data>
<country name="Panama">
<rank>69</rank>
<year>2026</year>
<gdppc>13600</gdppc>
<neighbor direction="w" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>
"""
4.4构建文档
from xml.etree import ElementTree as ET
# 创建根节点
root = ET.Element("home")
# 创建节点大儿子
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) # 把grandson1标签添加到son1标签中
son1.append(grandson2)
# 把儿子添加到根节点中
root.append(son1) # 把son1标签添加到root标签中
root.append(son2)
tree = ET.ElementTree(root)
tree.write('files/00.xml', encoding='utf-8', short_empty_elements=False)
# short_empty_elements=False,创建长标签,如<grandson name="儿11"></grandson>
# short_empty_elements=True,创建短标签,如<grandson name="儿11" />
# <home><son name="儿1"><grandson name="儿11"></grandson><grandson name="儿12"></grandson></son><son name="儿2"></son></home>
# 2.另一种方法
from xml.etree import ElementTree as ET
# 创建根节点
root = ET.Element("famliy")
# 创建大儿子
son1 = root.makeelement('son', {'name': '儿1'})
# 创建小儿子
son2 = root.makeelement('son', {'name': '儿2'})
# 在大儿子中创建两个孙子
grandson1 = son1.makeelement('grandson', {'name': '儿11'})
grandson2 = son1.makeelement('grandson', {'name': '儿12'})
son1.append(grandson1) # 把grandson1标签添加到son1标签中
son1.append(grandson2)
# 把儿子添加到根节点中
root.append(son1) # 把son1标签添加到root标签中
root.append(son2)
tree = ET.ElementTree(root)
tree.write('files/0X0.xml', encoding='utf-8', short_empty_elements=False)
# short_empty_elements=False,创建长标签,如<grandson name="儿11"></grandson>
# short_empty_elements=True,创建短标签,如<grandson name="儿11" />
# <famliy><son name="儿1"><grandson name="儿11"></grandson><grandson name="儿12"></grandson></son><son name="儿2"></son></famliy>
# 创建结果如下
<home>
<son name="儿1">
<grandson name="儿11"></grandson>
<grandson name="儿12"></grandson>
</son>
<son name="儿2"></son>
</home>
# 3.另一种方法
from xml.etree import ElementTree as ET
# 创建根节点
root = ET.Element('famliy')
# 直接创建根标签root的子标签
# 创建大儿子
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("files/test.xml", encoding='utf-8')
# 创建结果如下
<family>
<son name="儿1">
<age name="儿11">孙子</grandson>
</son>
<son name="儿2"></son>
</family>
对文本进行包裹
from xml.etree import ElementTree as ET
# 创建根节点
root = ET.Element("user")
root.text = "<![CDATA[你好呀]]"
et = ET.ElementTree(root) # 生成文档对象
et.write("test.xml", encoding= 'utf-8')
<user><![CDATA[你好呀]]</user>
案例
content = """<xml>
<ToUserName><![CDATA[gh_7f083739789a]]></ToUserName>
<FromUserName><![CDATA[oia2TjuEGTNoeX76QEjONrcURxG8]]></FromUserName>
<CreateTime>1395658920</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[TEMPLATESENDJOBFINISH]]></Event>
<MsgID>200163836</MsgID>
<Status><![CDATA[success]]</Status>
</xml>"""
# 实现如下解析
# 代码如下
from xml.etree import ElementTree as ET
info = {}
root = ET.XML(content)
for node in root:
print(node.tag, node.text) # 循环,拿到标签和对应的文本
info[node.tag] = node.text
print(info)
5.Excel格式文件
Python内部未提供处理Excel文件的功能,想要在Python中操作Excel需要按照第三方的模块。
pip install openpyxl
此模块中集成了Python操作Excel的相关功能,接下来我们就需要去学习该模块提供的相关功能即可。
5.1读Excel
- 读sheet
from openpyxl import load_workbook wb = load_workbook("files/p1.xlsx") # sheet相关操作 # 1.获取excel文件中的所有sheet名称 print(wb.sheetnames) # ['列表1', '列表2', '列表3'] # 2.选择sheet sheet = wb['列表1'] cell = sheet.cell(1, 1) print(cell.value) # 饱和水的物性参数表 # 3.选择sheet,基于索引位置 sheet = wb.worksheets[0] cell = sheet.cell(4, 5) print(cell.value) # m.W/(m.k) # 4.循环所有的sheet,3种方式 for name in wb.sheetnames: sheet = wb[name] cell = sheet.cell(2, 1) print(cell.value) for sheet in wb.worksheets: cell = sheet.cell(3, 1) print(cell.value) for sheet in wb: cell = sheet.cell(1, 2) print(cell.value)
- 读sheet中单元格的数据
from openpyxl import load_workbook wb = load_workbook("files/p1.xlsx") sheet = wb.worksheets[0] # 1.获取第N行第N列的单元格(位置是从1开始) cell = sheet.cell(1, 1) # 第1行第1列 print(cell.value) # 单元格值 print(cell.style) # 单元格样式 print(cell.font) # 单元格字体 print(cell.alignment) # 位置格式信息 # 2.获取某个单元格 c1 = sheet['A2'] print(c1.value) # 温度 c2 = sheet['D4'] print(c2.value) # kJ/kg # 3.第N行所有的单元格 print(sheet[1]) # 第1行所有单元格 for cell in sheet[1]: # 获取第1行所有单元格循环 print(cell.value) # 4.获取所有行数据(获取某一列数据) for row in sheet.rows: # 获取所有行循环 print(row[0].value, row[1].value) # 输出每行第0个、第1个单元格的值 # 5.获取所有列的数据 for col in sheet.columns: # 获取所有列循环 print(col[0].value, col[1].value) # 输出每列第0个、第1个单元格的值
- 读合并的单元格
from openpyxl import load_workbook
wb = load_workbook("files/p1.xlsx")
sheet = wb.worksheets[2]
# 获取第1行第1列的单元格(位置是从1开始)
c1 = sheet.cell(1, 1)
print(c1) # <Cell '列表1'.A1>
print(c1.value) # 饱和水的物性参数表
# 获取第2行第2列的单元格(位置是从1开始)
c2 = sheet.cell(2, 2)
print(c2) # <Cell '列表1'.B2>
print(c2.value) # 绝对 压力
5.2写Excel
在Excel中想要写文件, 大致要分为在:
- 原Excel文件基础上写内容。
from openpyxl import load_workbook
wb = load_workbook('files/pl.xlsx')
sheet = wb.worksheets[0]
# 找到单元格,并修改单元格的内容
cell = sheet.cell(1, 1)
cell.value = "新的开始"
# 将excel文件保存到p2.x1sx文件中
wb.save("files/p2.xlsx")
- 新创建Excel文件写内容。
from openpyxl import workbook
# 创建excel且默认会创建一个sheet(名称为Sheet)
wb = workbook.Workbook()
sheet = wb.worksheets[0] # 或 sheet = wb["Sheet"]
# 找到单元格,并修改单元格的内容
cell = sheet.cell(1, 1)
cell.value = "新的开始"
# 将exce1文件保存到p2.x1sx文件中
wb.save("files/p2.xlsx")
在了解了如何读取Excel和创建Excel之后, 后续对于Excel中的sheet和cell操作基本上都相同。
- 创建、修改sheet
from openpyxl import workbook
# 创建excel且默认会创建一个sheet(名称为Sheet)
wb = workbook.Workbook()
# 1.修改sheet名称
sheet = wb.worksheets[0]
sheet.title = '数据集'
wb.save("p2.xlsx")
# 2.创建sheet并设置sheet颜色
sheet = wb.create_sheet('工作计划', 0)
sheet.sheet_properties.tabColor = '1072BA'
wb.save("p2.xlsx")
# 3.默认打开的sheet
wb.active = 0
wb.save("p2.xlsx")
# 4.拷贝sheet
sheet = wb.create_sheet('工作计划')
sheet.sheet_properties.tabColor = '1072BA'
new_sheet = wb.copy_worksheet(wb['Sheet'])
new_sheet.title = '新的计划'
wb.save("p3.xlsx")
# 5.删除sheet
from openpyxl import load_workbook
wb = load_workbook('files/p2.xlsx')
del wb['列表2']
wb.save("files/p2.xlsx")
- 修改单元格
from openpyxl import load_workbook
from openpyxl.styles import Alignment, Border, Side, Font, PatternFill, GradientFill
wb = load_workbook("files/p1.xlsx")
sheet = wb.worksheets[1]
# 1.获取某个单元格,修改值
cell = sheet.cell(1, 1)
cell.value = '开始'
wb.save('p2.xlsx')
# 2.获取某个单元格,修改值
sheet['B3'] = 'GDL'
wb.save('p2.xlsx')
# 3.获取某些单元格,修改值
cell_list = sheet['B3':'C5']
for row in cell_list:
for cell in row:
cell.value = '新的值'
wb.save('p2.xlsx')
# 4.对齐方式
cell = sheet.cell(1, 1)
# horizontal,水平方向对齐方式:'general', 'left', 'center', 'right', 'fill', 'justify','centerContinuous', 'distributed'
# vertical,垂直方向对齐方式:'top', 'center', 'bottom', 'justify', 'distributed'
# text_rotation,旋转角度
# wrap_text,是否换行
cell.alignment = Alignment(horizontal='center', vertical='distributed', text_rotation='45', wrap_text=True)
wb.save('p2.xlsx')
# 5.边框
# side的style有如下:'dashDot'''dashDotDot'''dashed'''dotted'''double'''hair'''medium'''mediumDashDot''
cell = sheet.cell(9, 2)
cell.border = Border(
top=Side(style="thin", color="FFB6C1"),
bottom=Side(style="dashed", color="FFB6C1"),
left=Side(style="dashed", color="FFB6C1"),
right=Side(style="dashed", color="9932CC"),
diagonal=Side(style="thin", color="483D8B"), # 对角线
diagonalUp=True, # 左下-右上
diagonalDown=True # 左上-右下
)
wb.save("files/files/p2.xlsx")
# 6.字体
cell = sheet.cell(5, 1)
cell.font = Font(name="微软雅黑", size=45, color="ff0000", underline="single")
wb.save("files/p2.xlsx")
# 7.背景色
cell = sheet.cell(5, 3)
cell.fill = PatternFill("solid", fgColor="99ccff")
wb.save("files/p2.xlsx")
# 8.渐变背景色
cell = sheet.cell(5, 5)
cell.fill = GradientFill("linear", stop=("FFFFFF", "99ccff", "000000"))
wb.save("files/p2.xlsx")
# 9.宽高(索引从1开始)
sheet.row_dimensions[1].height = 50
sheet.column_dimensions["E"].width = 100
wb.save("files/p2.xlsx")
# 10.合并单元格
sheet.merge_cells("B2:D8")
sheet.merge_cells(start_row=15, start_column=3, end_row=18, end_column=8)
wb.save("files/p2.xlsx")
sheet.unmerge_cells("B2:D8") # 解除合并单元格
wb.save("files/p2.xlsx")
# 11.写入公式
sheet = wb.worksheets[3]
sheet["D1"] = '合计'
sheet["D2"] = "=B2*C2"
wb.save("file/p2.xlsx")
sheet = wb.worksheets[3]
sheet["D3"] = "=SUM(B3,C3)"
wb.save("file/p2.xlsx")
# 12.删除
# idx,要删除的索引位置
# amount,从索引位置开始要删除的个数(默认为1)
sheet.delete_rows(idx=1, amount=2) # 从第1行开始向后再数2行删掉
sheet.delete_cols(idx=1, amount=3) # 从第1列开始向后再数3列删掉
wb.save("file/p2.xlsx")
# 13.插入
sheet.insert_rows(idx=5, amount=10) # 从第1行开始向后插入10行
sheet.insert_cols(idx=3, amount=2) # 从第3列开始向后插入2列
wb.save("file/p2.xlsx")
# 14.循环写内容
sheet = wb["Sheet"]
cell_range = sheet['A1:C2']
for row in cell_range:
for cell in row:
cell.value = "xx"
for row in sheet.iter_rows(min_row=5, min_col=1, max_col=7, max_row=10):
for cell in row:
cell.value = "oo"
wb.save("file/p2.xlsx")
# 15.移动
# 将H2:J10范围的数据,向右移动15个位置、向上移动1个位置
sheet.move_range("H2:J10", rows=-1, cols=15) # 负值表示向上/向左移动
wb.save("file/p2.xlsx")
sheet = wb.worksheets[3]
sheet["D1"] = "合计"
sheet["D2"] = "=B2*C2"
sheet["D3"] = "=SUM(B3,C3)"
sheet.move_range("B1:D3", cols=10, translate=True) # 自动翻译公式
wb.save("file/p2.xlsx")
# 16.打印区域
sheet.print_area = "A1:D20"
wb.save("file/p2.xlsx")
# 17.打印时,每个页面的固定表头
# 保留A~D列,1~3行的表头
sheet.print_title_cols = "A:D"
sheet.print_title_rows = "1:3"
wb.save("file/p2.xlsx")
在了解了如何读取Excel和创建Excel之后, 后续对于Excel中的sheet和cell操作基本上都相同。
6.压缩文件
基于Python内置的shutil模块可以实现对压缩文件的操作。
import shutil
# 1.压缩文件
# base_name,压缩后的压缩包文件
# format,压缩的格式,例如:"zip","tar","gztar","bztar",or"xztar".
# root_dir,要压缩的文件夹路径
shutil.make_archive(base_name=r'datafile', format='zip', root_dir=r'files')
# 2.解压文件
# filename,要解压的压缩包文件
# extract_dir,解压的路径
# format,压缩文件格式
shutil.unpack_archive(filename=r'datafile.zip', extract_dir=r'XXXX/XO', format='zip')
7.路径相关
7.1 转义
windows路径使用的是\,linux路径使用的是/。
特别的,在windows系统中如果有这样的一个路径D:\nxxx\txxx\x1,程序会报错。因为在路径存在特殊符\n(换行符)和\t(制表符),Python解释器无法自动区分。
所以,在windows中编写路径时,一般有两种方式:
加转义符,例如:”D:\\nxxx\\txxx\\x1″
路径前加r,例如:r”D:\nxxx\xxx\x1″
7.2程序当前路径
项目中如果使用了相对路径,那么一定要注意当前所在的位置。
例如:在/Users/wupeigi/PycharmProjects/CodeRepository/
路径下编写 demo.py
文件
with open("a1.txt", mode='w', encoding='utf-8')as f:
f.write("你好呀")
用以下两种方式去运行:
- 方式1,文件会创建在
/Users/wupeigi/PycharmProjects/CodeRepository/
目录下。cd/Users/wupeigi/PycharmProjects/CodeRepository/ python demo.py
- 方式2,文件会创建在
/Users/wupeiqi
目录下。cd/Users/wupeigi python/Users/wupeiqi/PycharmProjects/CodeRepository/demo.py
例:
import os # 1.获取当前运行的py脚本所在的路径 abs = os.path.abspath(__file__) print(abs) # F:\BaiduSyncdisk\Python\试验.py # 获取当前py文件的上一级目录,也即项目的根目录 path = os.path.dirname(abs) print(path) # F:\BaiduSyncdisk\Python # 上述代码集成写法 base_dir = os.path.dirname(os.path.abspath(__file__)) print(base_dir) # F:\BaiduSyncdisk\Python # 拼接路径,此路径为绝对路径 # file_path = base_dir + '/files/info.txt' file_path = os.path.join(base_dir, 'files', 'info.txt') # 上句代码实际应用这样写可兼容不同系统对路径格式的不同 print(file_path) # F:\BaiduSyncdisk\Python\files\info.txt if os.path.exists(file_path): # 只有文件存在才读取 # 写入内容 file_object = open(file_path, mode='r', encoding='utf-8') data = file_object.read() file_object.close() print(data) else: print('文件路径不存在')
7.3文件和路径相关
import shutil
import os
# 1.获取当前脚本绝对路径
abs_path = os.path.abspath(__file__)
print(abs_path) # F:\BaiduSyncdisk\Python\试验.py
# 2.获取当前文件的上级目录
base_path = os.path.dirname(os.path.abspath(__file__))
print(base_path) # F:\BaiduSyncdisk\Python
# 3.路径拼接
p1 = os.path.join(base_path, 'xx')
print(p1) # F:\BaiduSyncdisk\Python\xx
p2 = os.path.join(base_path, 'xx', 'oo', 'al.png')
print(p2) # F:\BaiduSyncdisk\Python\xx\oo\al.png
# 4.判断路径是否存在
exists = os.path.exists(p1)
print(exists) # False
# 5.创建文件夹
# os.makedirs('路径')
path = os.path.join(base_path, 'xx', 'oo', 'uuuu')
if not os.path.exists(path):
os.makedirs(path)
# 6.是否是文件夹
file_path = os.path.join(base_path, 'xx', 'oo', 'uuuu.png')
is_dir = os.path.isdir(file_path)
print(is_dir) # False
folder_path = os.path.join(base_path, 'xx', 'oo', 'uuuu')
is_dir = os.path.isdir(folder_path)
print(is_dir) # True
# 7.删除文件或文件夹
# shutil.rmtree('路径')
path = os.path.join(base_path, 'xx')
shutil.rmtree(path)
# 8.拷贝文件夹
shutil.copytree("/Users/wupeigi/Desktop/g/csdn/", "/Users/wupeigi/PycharmProjects/CodeRepository/files") # 拷贝前文件夹到后目录内
# 9,拷贝文件
shutil.copy("/Users/wupeigi/Desktop/g/csdn/wx20201123-1124062x.png", "/Users/wupeigi/PycharmProjects/CodeRepository/") # 拷贝前图片到后文件夹里
shutil.copy("/Users/wupeiqi/Desktop/g/csdn/wx20201123-11240682x.png",
"/Users/wupeigi/PycharmProjects/CodeRepository/x.png") # 拷贝前图片到后文件夹后重命名为X
# 10.文件或文件夹重命名(移动)
shutil.move("/Users/wupeigi/PycharmProjects/CodeRepository/x.png",
"/Users/wupeigi/PycharmProjects/CodeRepository/xxxx.png")
shutil.move("/Users/wupeiqi/PycharmProjects/CodeRepository/files",
"/Users/wupeigi/PycharmProjects/CodeRepository/images")