Python 文件操作魔法手册:open函数的终极艺术

liftword1个月前 (03-29)技术文章14

Python 文件操作魔法手册:open 函数的终极艺术



对话实录

小白:(崩溃)我写了open("data.txt"),为什么报错?

专家:(掏出魔法书)文件操作要小心,模式、编码都要注意


open 函数基础三连击

1. 基本用法

# 读取文件
with open("data.txt", "r", encoding="utf-8") as f:
 content = f.read()

# 写入文件
with open("output.txt", "w") as f:
 f.write("Hello World!")

专家提醒:一定要用with语句,它能在代码块结束时自动关闭文件,防止资源泄露。想象一下,你打开一扇门进入房间,离开时却忘记关门,这可能会带来安全隐患。在文件操作中,忘记关闭文件就如同忘记关门,可能导致数据丢失或系统资源被占用。使用with语句就像是有一个贴心的助手,在你离开房间时自动帮你关门。

2 open函数参数介绍

open函数的参数

open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)

1)file:传入不带路径的字符串(文本文件/二进制文件)或者带有绝对路径或者相对路径的文件。如果传入的文件不存在,默认会创建文件。

如果传入的文件不合要求,会报错如下:

2)mode:指明文件打开模式的可选字符串。默认为‘r’表示以文本模式读取。

字符

含意

'r'

只读取(默认);文件必须存在,否则会报错。

'w'

只写入,是覆盖式写入(比如第一次写入后,再次打开以w方式写入会覆盖原内容。)

'x'

排它性创建,如果文件已存在则失败。如果文件不存在则创建,模式为写入,与'w'类似。

'a'

只写入,再次打开文件并不会覆盖,而是在末尾追加写入。

'b'

表示二进制模式读取和写入,不能单独使用,须与'r','w','a','x'配合使用。

比如打开一张图片文件,如果用文本模式打开,看到的将是一堆乱码,因为图片数据是二进制格式,需要用二进制模式正确读取。

't'

文本模式(默认),与'r','w','a','x'配合使用。

比如'r'与'rt'同义,一般直接使用'r'。

'+'

打开用于更新(读取与写入),不能单独使用,须与'r','w','a','x'配合使用。

以上模式结合使用:

a. 只读取:'r',’rb’

b. 只写入:'w',’wb’,’a’,’ab’,'x','xb'

c. 读取和写入:'r+',’r+b’,'w+',’w+b’,’a+’,’a+b’,’x+’,’x+b’

  • 'r+':以读写模式打开文件,文件指针会放在文件的开头。
  • 'w+':以读写模式打开文件,原文件内容会被删除。(慎用)
  • 'a+':以读写模式打开文件用于追加,文件指针会放在文件的末尾(表现为以a+模式打开文件直接读取内容,读取的内容为空)。

在读取和写入模式下我们可以使用seek()方法来移动文件指针到指定位置,以便在文件的任意位置进行读写操作。

3)buffering:参数可选,表示设置缓冲策略,默认为None。0表示无缓冲(仅适用于二进制模式),大于0表示缓冲区的大小(以字节为单位)。

4)encoding:参数可选,默认为系统默认编码(在Python 3中通常是UTF-8);在文本模式下可以指定编码,在二进制模式下不需要指定编码。

5)errors:参数可选,指定编码和解码错误的处理方式。默认为None,跟值'strict'效果一样,表示严格处理错误,其他值如'ignore'用于忽略错误、'replace'替换一些错误标记等。

5)newline:参数可选,用于控制文件读取和写入时行的结束符。默认为None,表示使用系统默认的行结束符,比如'\r\n','\n'。在文本模式下读取文件时,默认把平台特定的行结束符(Unix 上为 \n, Windows 上为 \r\n)转换为 \n。在文本模式下写入数据时,默认把 \n 转换回平台特定结束符。

6)closefd:参数可选,closefd默认为True表示当文件对象被关闭时,同时关闭文件描述符,防止资源泄漏。当closefd为False指当文件对象被关闭时,不关闭文件描述符。当file参数传入的是文本文件时,该参数必须为Ture,否则会报错。

3 常用方法介绍

1)读取方法

  • read(size=-1):从文件中读取并返回指定数量的字符或者字节,如果不指定size则读取并返回文件的全部内容。
  • readline(size=-1):从文件中读取并返回一行(直到换行符 \n),或返回指定数量的字节。
  • readlines(hint=-1):读取所有行并返回列表,其中每一行都是一个字符串。如果指定了 hint,则读取指定数量的字符或者字节。

2)写入方法

  • write(str):将字符串或字节写入文件,只写入一行,并且不会在末尾添加换行符,需要自己添加。
  • writelines(lines):向文件写入一个字符串或者字节列表,可写入多行,并且不会在末尾添加换行符,需要自己添加。

3)移动文件对象指针位置

  • seek(offset, whence=0):移动文件读取指针到指定位置。offset 是指从 whence 指定的位置开始计算的字符或者字节数。whence 的值为 0(文件开头,默认值)、1(当前位置)或 2(文件末尾)。
  • tell():返回文件当前的指针位置。

4)关闭文件对象

close():关闭文件对象。

其他方法

flush():将缓冲区的内容写入文件,但不关闭文件。

fileno():返回文件的描述符(一个小的非负整数)。

isatty():如果文件是一个与终端设备(tty)相关联的,则返回 True,否则返回 False.

readable()writable()seekable():分别用于检查文件是否可读、可写、以及是否支持 seek() 操作。

truncate(size=None):截断文件到指定大小。如果 size 未指定,则截断文件到当前位置。如果当前位置大于文件大小,则文件将被扩展,并且扩展部分的内容将用零字节填充。

4 常用属性介绍

  • name 属性:返回打开文件的名称。
  • closed 属性:返回一个布尔值,指示文件是否已关闭。当文件被成功打开时,closed 属性为 False。一旦文件被关闭,closed属性为True。
  • mode属性:返回open函数传入的mode值。
  • encoding属性:返回open函数使用的编码。
  • buffer属性:返回open函数的buffer配置。
  • errors属性:返回open函数的errors配置。

六大实战案例

案例 1:逐行读取大文件

#  错误示范
with open("big.txt") as f:
 lines = f.readlines() # 内存爆炸!

这种方式会一次性将整个文件读入内存,如果文件非常大,可能会耗尽系统内存,导致程序崩溃。

# 正确做法
with open("big.txt") as f:
 for line in f: # 逐行读取
  process(line)

逐行读取大文件,每次只在内存中处理一行数据,大大降低了内存压力。

案例 2:CSV 文件处理

import csv
with open("data.csv", newline="") as f:
 reader = csv.reader(f)
 for row in reader:
   print(row)

CSV(Comma - Separated Values)文件常用于存储表格数据,如数据库导出的数据。使用csv模块可以方便地读取和写入 CSV 文件。在这个例子中,newline=""参数用于避免在读取 CSV 文件时出现额外的空行,确保数据读取的准确性。

案例 3:JSON 文件读写

import json
# 读取json文件内容为python对象
with open("data.json") as f:
 data = json.load(f)
 # 将python对象写入json文件
with open("output.json", "w") as f:
 json.dump(data, f, indent=2)

JSON(JavaScript Object Notation)文件常用于存储结构化数据,在 Web开发和数据交换中广泛应用。json.load(f)用于将文件中的JSON 数据解析为Python 对象,json.dump(data, f, indent = 2)则将 Python 对象转换为JSON 格式并写入文件,indent = 2参数使生成的JSON文件更加美观易读,数据层次结构一目了然。

案例 4:XML 文件解析

import xml.etree.ElementTree as ET
tree = ET.parse("data.xml")
root = tree.getroot()
for child in root:
 print(child.tag, child.attrib)

XML(eXtensible Markup Language)也是一种常用的结构化数据格式,常用于配置文件和数据交换。通过xml.etree.ElementTree模块可以轻松解析 XML 文件。在这个例子中,我们使用ET.parse方法读取 XML 文件,然后获取根元素,并遍历根元素的子元素,打印出每个子元素的标签和属性。

案例 5:日志文件处理

import logging
logging.basicConfig(filename='app.log', level=logging.INFO)
logging.info('程序开始运行')
try:
 result = 1 / 0
except ZeroDivisionError as e:
 logging.error(f'发生错误: {e}')
logging.info('程序结束运行')

在开发应用程序时,记录日志是非常重要的。它可以帮助我们追踪程序的运行状态,排查错误。通过logging模块,我们可以方便地将日志信息写入文件。在这个例子中,我们设置日志级别为INFO,记录程序的开始和结束运行信息,并在发生ZeroDivisionError错误时记录错误信息到app.log文件中。

案例 6:图片文件处理(简单的图片格式转换)

from PIL import Image
try:
 img = Image.open('input.jpg')
 img.save('output.png', 'PNG')
except Exception as e:
 print(f'处理图片时发生错误: {e}')

使用 Python 的PIL(Python Imaging Library)库可以对图片进行各种处理,如格式转换、裁剪、调整大小等。在这个例子中,我们将一张 JPEG 格式的图片转换为 PNG 格式。Image.open方法用于打开图片文件,img.save方法用于将图片保存为指定格式。

四大血泪陷阱

忘记关闭文件

# 错误示范
f = open("data.txt")
content = f.read()
# 忘记f.close() 

在这种情况下,文件在读取操作完成后没有被关闭,可能会导致资源泄露。如果程序中多次出现这种情况,可能会耗尽系统的文件描述符资源,导致程序无法再打开新的文件。

#  正确做法
with open("data.txt") as f:
 content = f.read()

with语句会自动管理文件的生命周期,在代码块结束时关闭文件,确保资源得到正确释放。

编码问题

# 错误示范
with open("data.txt") as f: # 默认编码可能出错
 content = f.read()

不同的操作系统和文本编辑器可能使用不同的默认编码。如果在打开文件时不指定编码,可能会导致读取文件时出现乱码或UnicodeDecodeError错误。例如,在 Windows 系统中,默认编码可能是cp936,而在处理包含非 ASCII 字符的文件时,可能会出现编码不匹配的问题。

# 正确做法
with open("data.txt", encoding="utf-8") as f:
 content = f.read()

显式指定编码为utf - 8,这是一种通用的编码格式,能够处理各种语言的字符,避免编码问题。

路径问题

# 错误示范
open("data.txt") # 相对路径可能出错

使用相对路径时,文件的实际位置取决于当前工作目录。如果在不同的环境中运行程序,或者当前工作目录被改变,可能会导致找不到文件。比如,在一个脚本中使用相对路径open("data.txt"),在脚本所在目录运行程序时可以正常找到文件,但如果在其他目录运行,就可能找不到该文件。

# 正确做法
from pathlib import Path
file = Path(__file__).parent / "data.txt"
with open(file) as f:
 content = f.read()

使用Pathlib模块来处理路径,它提供了一种跨平台的路径操作方式。Path(__file__).parent获取当前脚本所在的目录,然后通过/运算符拼接文件名,确保无论在何种环境下都能正确定位文件。

文件模式误用

# 错误示范
with open("data.txt", "w") as f:
 data = f.read() # 写入模式下不能读取

在这种情况下,以w(写入)模式打开文件后,尝试读取文件内容,会导致io.UnsupportedOperation错误,因为w模式只允许写入操作,不允许读取。

# 正确做法
with open("data.txt", "r+") as f:
 data = f.read()
 f.write("追加的内容")

如果需要对文件进行读写操作,应使用合适的模式,如r+模式,它允许在读取文件的同时进行写入操作。

专家工具箱

1. 二进制文件操作

# 读取图片
with open("image.png", "rb") as f:
 data = f.read()
# 写入二进制
with open("output.bin", "wb") as f:
 f.write(b"\x00\x01\x02")

二进制文件操作在处理图片、音频、视频等非文本文件时非常重要。在读取图片时,使用rb(二进制读取)模式,确保文件内容被正确读取。写入二进制数据时,使用wb(二进制写入)模式,数据以字节形式写入文件。例如,b"\x00\x01\x02"表示写入三个字节的数据,每个字节的值分别为 0、1、2。

2. 文件指针操作

with open("data.txt") as f:
f.seek(10) # 移动到第10字节
 print(f.read(5)) # 读取5个字符


文件指针用于指示当前文件读取或写入的位置。f.seek(offset, whence)方法用于移动文件指针,offset表示偏移量,whence表示参考位置,0 表示文件开头,1 表示当前位置,2 表示文件末尾。在这个例子中,f.seek(10)将文件指针移动到第 10 个字节的位置,然后f.read(5)从该位置读取 5 个字符。通过灵活操作文件指针,可以实现对文件内容的随机访问,比如读取文件中间某一段特定的数据。

3. 临时文件

from tempfile import TemporaryFile
with TemporaryFile("w+") as f:
 f.write("临时数据")
 f.seek(0)
 print(f.read())

临时文件在程序运行过程中用于临时存储数据,当程序结束时,临时文件会自动被删除。TemporaryFile函数创建一个临时文件,w+模式表示可读写。在这个例子中,我们先写入一些临时数据,然后将文件指针移回开头,读取并打印这些数据。使用临时文件可以避免在磁盘上留下不必要的文件,同时保证数据的安全性,因为临时文件在程序结束后会自动消失,不用担心数据残留问题。

小白:(献上膝盖)原来文件操作这么讲究!

专家:(扶起小白)记住:文件操作要小心,资源泄露是大忌!

相关文章

一文掌握Python找到文件操作

阅读文件读取文件的全部内容:with open('example.txt', 'r') as file: content = file.read() print(content)2....

小白零基础用Python半小时搞定TXT转PDF!附赠脚本

"原来根本不用充会员!" 昨天我还在为100本TXT电子书无法上传腾讯ima知识库急得跳脚,今天却用60行Python代码实现了全自动转换pdf(全程没花1分钱)。作为一个连安装软件都要百度的新手,这...

Python 文件读写(txt、json、xml、ini)

在进行接口自动化测试时,我们经常需要处理各种格式的文件。熟练掌握对这些文件的读写能力对于提升测试效率至关重要。今天我们就来一起学习如何用Python来操作常见的文件类型,包括文本文件(.txt)、JS...

22-3-Python高级特性-上下文管理器

4-上下文管理器4-1-概念上下文管理器是一种实现了 `__enter__()` 和 `__exit__()` 方法的对象;用于管理资源的生命周期,如文件的打开和关闭、数据库连接的建立和断开等。使用...

21-01-Python-文件操作上

在Python中,文件操作是非常重要的一部分,它允许我们读取、写入和修改文件。下面将详细讲解Python文件操作的各个方面,并给出相应的示例。1-打开文件在Python中,使用`open()`函数来打...

高效办公:Python处理excel文件,摆脱无效办公

一、Python处理excel文件1. 两个头文件import xlrd import xlwt其中xlrd模块实现对excel文件内容读取,xlwt模块实现对excel文件的写入。2. 读取exce...