Python基础-15.file操作

TOC

一、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)来读取文件内容