Python基础-15.file操作
一、Python文件操作基础
open方法
Python open() 方法用于打开一个文件,并返回文件对象。
在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出OSError。
注意:使用
open()方法一定要保证关闭文件对象,即调用close()方法。
open()函数常用形式是接收两个参数:文件名(file)和模式(mode)。
语法:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数说明:
- file: 必需,文件路径(相对或者绝对路径)。
- mode: 可选,文件打开模式
- buffering: 设置缓冲
- encoding: 一般使用utf8
- errors: 报错级别
- newline: 区分换行符
- closefd: 传入的file参数类型
- opener: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符。
open方法mode参数
mode参数可以指定open方法打开文件的模式,列表如下:
| 参数 | 模式 | 描述 | 常用指数 |
|---|---|---|---|
| t | 文本模式(默认)。 | ❌ | |
| x | 写模式,新建一个文件,如果该文件已存在则会报错。 | ❌ | |
| b | 二进制模式。 | ✅ | |
| + | 打开一个文件进行更新(可读可写)。 | ❌ | |
| U | 通用换行模式(Python 3 不支持)。 | ❌ | |
| r | 读 | 以只读方式打开文件,指针在文件开头(默认模式)。 | ✅ |
| rb | 读 | 以二进制格式只读,指针在开头,常用于非文本文件如图片。 | ✅ |
| r+ | 读写 | 读写模式,指针在开头。 | ✅ |
| rb+ | 读写 | 以二进制格式读写,指针在开头,常用于非文本文件如图片。 | ✅ |
| w | 写 | 只写模式,如果文件已存在则清空,从头写入;不存在则新建。 | ✅ |
| wb | 写 | 二进制只写,文件存在则清空,从头写入;不存在则新建。常用于非文本文件。 | ✅ |
| w+ | 读写 | 读写模式,文件存在则清空,从头写入;不存在则新建。 | ✅ |
| wb+ | 读写 | 二进制读写,文件存在则清空,从头写入;不存在则新建。常用于非文本文件。 | ✅ |
| a | 写 | 追加写模式,文件存在则指针在结尾,写入新内容;不存在则新建。 | ✅ |
| ab | 写 | 二进制追加写,文件存在则指针在结尾;不存在则新建。 | ✅ |
| a+ | 读写 | 读写模式,指针在结尾(追加模式);不存在则新建。 | ✅ |
| ab+ | 读写 | 二进制读写追加模式,指针在结尾;不存在则新建。 | ✅ |
file对象方法
file对象使用open函数来创建,下表列出了file对象常用的函数:
| 方法 | 描述 | 常用指数 |
|---|---|---|
| file.close() | 关闭文件,关闭后文件不能再进行读写操作。 | ✅ |
| file.flush() | 刷新文件内部缓冲区,把数据立即写入文件,而不是等待缓冲区写入。 | ❌ |
| file.fileno() | 返回文件描述符(整型 FD),可用于 os 模块的底层操作。 | ❌ |
| file.isatty() | 判断文件是否连接到终端设备,是则返回 True,否则 False。 | ❌ |
| file.next() | (Python 3 不支持)返回文件下一行。 | ❌ |
| file.read([size]) | 读取指定字节数;若未指定或为负,则读取整个文件。 | ✅ |
| file.readline([size]) | 读取一整行,包括换行符 “\n”。 | ✅ |
| file.readlines([sizeint]) | 读取所有行并返回列表;若指定 sizeint,则读取的总字节数大约为该值。 | ✅ |
| file.seek(offset[, whence]) | 移动文件指针到指定位置。 | ❌ |
| file.tell() | 返回文件当前指针位置。 | ❌ |
| file.truncate([size]) | 从文件开头截断为指定大小;若未指定,则从当前位置截断。 | ❌ |
| file.write(str) | 将字符串写入文件,返回写入的字符数。 | ✅ |
| file.writelines(sequence) | 将字符串序列写入文件,需手动添加换行符。 | ✅ |
开始操作文件
简单操作示例
【示例】使用r只读模式打开test.txt文件,并读取其中的内容
file = open("test.txt", "r") # 打开文件
content = file.read() # 读取文件内容
f.close() # 关闭文件
使用with…as
如果中间file.read()抛出了异常(比如文件过大、编码错误等),那么file.close() 就不会执行,文件资源可能就一直占用着没释放。
with...as是上下文管理器的语法糖,用来保证资源的正确释放,写起来也相比使用try简便一些。
【示例】根据上面内容使用with...as来写
with open('test.txt', 'r') as file:
content = file.read()
file.close()
等价于以下异常写法:
file = open("test.txt", "r")
try:
content = file.read()
finally:
file.close()
open方法使用
文件读取:read()
读取文件内容
with open('test.txt', 'r', encoding='utf-8') as f:
data = f.read()
f.close()
读取二进制文件
with open('test.bin', 'rb') as f:
content = f.read()
print(content)
文件写入:write()
写入内容到文件
txt = '''this is a test
you have a test!!!
'''
with open('test.txt', 'r', encoding='utf-8') as f:
f.write(txt)
f.close()
写入二进制文件
with open('test.bin', 'wb') as f:
f.write(b'\x00\x01\x02\x03\x04')
逐行读取
逐行读取可以使用readline()或readlines()函数,但是想要一次性逐行读取文件全部内容就使用readlines()函数,因为readline()函数每次只会读取一行的数据。
创建一个文件file.txt文件,方便下面示例使用,内容如下:
Hello,Python!!!
I am currently learning Python.
readline()
用于读取文件中的一行,包含最后的换行符\n,如果需要继续读取,再次调用方法即可。
【示例】读取上面创建file.txt文件的第一行
with open('file.txt', 'r+', encoding='utf-8') as f:
data = f.readline()
print('第一次读取的内容:', data)
# 第二次读取限制最多可以读取的字符为3
data = f.readline(3)
print('第二次读取的内容:', data)
f.close()
'''运行结果如下
第一次读取的内容: Hello,Python!!!
第二次读取的内容: I a
'''
readlines()
用于读取文件中的所有行,该函数返回是一个字符串列表,其中每个元素为文件中的一行内容。
【示例】逐行读取上面创建file.txt文件全部内容
with open('file.txt', 'r+', encoding='utf-8') as f:
data = f.readlines()
print(data)
f.close()
'''运行结果如下
['Hello,Python!!!\n', 'I am currently learning Python.']
'''
文件指针操作:seek()
可以使用seek()和tell()方法来操作文件指针的位置。seek(offset, whence)方法用于移动文件指针,而tell()方法返回当前文件指针的位置。
with open('test.txt', 'r+', encoding='utf-8') as f:
# 移动文件指针到文件开始处
f.seek(0)
content = f.read(10) # 读取前10个字符
print(content) # 输出文件的前10个字符
# 将文件指针移动到文件末尾
f.seek(0, 2)
position = f.tell() # 获取当前文件指针位置(即文件大小)
print(f"File size: {position} bytes")
二、Python文件操作进阶
1.文件锁定
在处理多进程或多线程环境中的文件时,你可能需要锁定文件以防止数据竞争。Python的fcntl或msvcrt模块(Windows系统)提供了文件锁定的功能。
以下是一个在Unix-like系统上使用fcntl模块锁定文件的例子:
import fcntl
with open('test.lock', 'w') as f:
# 对文件加锁,F_WRLCK表示写锁,F_SETLK表示设置锁
fcntl.flock(f, fcntl.LOCK_EX) # LOCK_EX 是排它锁(写锁)
# 在此处进行文件写入操作...
f.write("Locked content")
# 解锁文件
fcntl.flock(f, fcntl.LOCK_UN) # LOCK_UN 解锁
在Windows上,你可以使用msvcrt模块来实现类似的功能:
import msvcrt
with open('test.lock', 'w') as f:
# 锁定文件区域,防止其他进程访问。注意,这里的锁定是区域性的。
msvcrt.locking(f.fileno(), msvcrt.LK_LOCK, 10) # 锁定前10个字节
# 在此处进行文件写入操作...
f.write("Locked content")
# 解锁文件区域
msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, 10) # 解锁前10个字节
2.文件复制
自己写一个方法进行文件的复制。
def copy_file(src, dst):
with open(src, 'rb') as source_file, open(dst, 'wb') as destination_file:
destination_file.write(source_file.read())
copy_file('src.txt', 'dst.txt')
3.文件移动和重命名以及删除
下列操作均用os模块来实现,用rename()方法移动并重命名文件
import os
def move_file(src, dst):
os.rename(src, dst)
move_file('old.txt', 'test/new.txt')
# 用remove()方法删除文件
os.remove('old.txt')
4.文件搜索
你可以使用os.walk()函数遍历目录树,并搜索特定类型的文件。
import os
# 搜索当前目录及其子目录下所有的.txt文件
def find_files(directory, extension):
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(extension):
yield os.path.join(root, file)
for txt_file in find_files('.', '.txt'):
print(txt_file)
# 找出该目录下所有的文件
def ls_file(search_path):
for root, dirs, files in os.walk(search_path):
for file in files:
list_file = os.path.join(root, file)
print(list_file)
5.处理文件编码问题
当处理文本文件时,编码是一个重要的问题。Python 3 默认使用 UTF-8 编码,但在某些情况下,你可能需要处理使用其他编码的文件。你可以通过指定open函数的encoding参数来处理这个问题。
读取一个使用 GBK 编码的文件:
with open('gbk_file.txt', 'r', encoding='gbk') as f:
content = f.read()
print(content)
写入一个使用 ISO-8859-1 编码的文件:
with open('iso_8859_1_file.txt', 'w', encoding='iso-8859-1') as f:
f.write('Some text with special characters: á, é, í, ó, ú.')
6.文件操作的异常处理
当进行文件操作时,可能会遇到各种问题,如文件不存在、无权限访问、磁盘空间不足等。为了确保程序的健壮性,应该对这些潜在问题进行异常处理。
try:
with open('non_existent_file.txt', 'r') as file:
content = file.read()
except FileNotFoundError:
print("文件不存在!")
三、shutil库
shutil是Python的标准库,主要用于文件和目录的高级操作,比如复制、移动、打包等。
使用shutil库需要先导入,如下所示:
import shutil
文件复制
文件复制有copy()和copy2()两个方法。
copy()方法
复制文件到目标目录或文件,保留内容和权限(但不保留其他元数据,如创建时间)。
【示例】把a.txt复制成backup.txt
shutil.copy("a.txt", "backup.txt")
copy2()方法
和copy类似,但会保留文件的所有元数据(目录权限、时间戳等)。
【示例】
shutil.copy2("a.txt", "backup.txt")
目录复制
使用copytree()方法,递归复制整个目录树,如果目标目录已存在会报错(Python 3.8+可以用dirs_exist_ok=True覆盖)。
【示例】
shutil.copytree("dir1", "dir2")
进行覆盖(Python 3.8+)
shutil.copytree("dir1", "dir2", dirs_exist_ok=True)
文件目录移动
使用move()方法,相当于Linux的mv命令,可以移动文件或目录。
【示例】
shutil.move("backup.txt", "backup/backup.txt")
删除整个目录
使用rmtree()方法可以递归删除整个目录树。
【示例】
shutil.rmtree("backup/")
注意:类似于Linux中的
rm -rf,需谨慎使用!!!
压缩与解压
使用make_archive()方法可以打包目录为压缩文件(支持打包格式:zip、tar、gztar、bztar、xztar)。
压缩文件
【示例】打包backup目录生成backup.zip文件
shutil.make_archive("backup", "zip", "myfolder")
解压文件
【示例】解压backup.zip文件到mydir目录下
shutil.unpack_archive("backup.zip", "mydir")
获取磁盘信息
还可以使用disk_usage()方法来获取磁盘使用情况(总空间、已用空间、剩余空间,单位字节)。
【示例】
total, used, free = shutil.disk_usage("/")
print(f"总空间: {total // (2**30)} GB")
print(f"已用: {used // (2**30)} GB")
print(f"可用: {free // (2**30)} GB")
温馨提示:方法里面参数跟目录,Windows和MacOS系统的磁盘结构不一样,需注意。
四、Python其他文件操作方式
1.目录操作
创建、删除目录以及列出目录内容等操作可以通过os模块来实现。
import os
# 创建目录
os.makedirs('new_directory', exist_ok=True) # 如果目录已存在,则不会引发错误
# 列出目录内容
contents = os.listdir('.') # 列出当前目录下的所有文件和子目录
print(contents)
# 删除目录
os.rmdir('new_directory') # 只能删除空目录
# 或者使用shutil模块删除非空目录
import shutil
shutil.rmtree('non_empty_directory') # 删除非空目录及其内容
2.pathlib库
from pathlib import Path
# 创建文件
p = Path('example.txt')
p.write_text('Hello, world!')
# 读取文件
content = p.read_text()
print(content) # 输出: Hello, world!
# 检查文件是否存在
if p.exists():
print(f"{p} exists.")
# 删除文件(如果文件存在)
if p.exists():
p.unlink() # 删除文件,与 os.remove() 功能相同
3.临时文件处理-tempfile库
Python的tempfile模块允许你轻松地创建临时文件和目录。
import tempfile
# 创建一个临时文件
with tempfile.NamedTemporaryFile(delete=False) as tmpfile:
tmpfile.write(b'Hello, temporary file!')
tmpfile_path = tmpfile.name # 获取临时文件的路径
print(f'Temporary file path: {tmpfile_path}')
# 创建一个临时目录
with tempfile.TemporaryDirectory() as tmpdirname:
print(f'Temporary directory created: {tmpdirname}')
# 你可以在这个临时目录中创建文件,进行临时操作等。
# 当with块结束时,临时目录及其内容将被自动删除。
4.压缩文件操作-zipfile库
处理压缩文件(如zip文件)时,你可以使用Python的zipfile模块。
import zipfile
# 创建一个zip文件并添加文件到其中
with zipfile.ZipFile('example.zip', 'w', zipfile.ZIP_DEFLATED) as zipf:
zipf.write('file1.txt')
zipf.write('file2.txt')
# 读取zip文件中的内容
with zipfile.ZipFile('example.zip', 'r') as zipf:
for filename in zipf.namelist():
print(filename)
# 可以使用zipf.read(filename)来读取文件内容