Python2.文件操作相关
本文最后更新于524 天前,其中的信息可能已经过时,如有错误请发送邮件到gedaling@foxmail.com

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)

image-20231130172553757

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()自带的换行符

image-20231130173037240

5.根据要求修改文件的内容,原文件内容如下:ha.conf

image-20231130173452724

请将文件中的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

image-20231130174328636

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

image-20231130175330247

这种格式是可以直接使用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协议等。

    image-20231130181608327

注意:在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")

 

 

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇