Python文件处理

文件处理是编程核心能力之一,可实现程序与文件系统交互,完成文件读取、写入、编辑及删除操作。在运维与企业业务场景中,文件处理广泛应用于日志运维、数据备份、文件规整清理等实际工作。

一、文件基础操作

在 Python 中,文件操作通过内置函数 open() 实现。可以使用不同模式打开文件,常用模式如下:

  • 'r':只读模式(默认)
  • 'w':写入模式(会覆盖原有内容)
  • 'a':追加模式(在文件末尾添加内容)

文件操作完成后必须关闭文件以释放系统资源。Python 提供了 file.close() 方法手动关闭文件,更推荐使用 with 语句,它会在代码块结束后自动关闭文件,更安全、更简洁。

案例:

file文件夹下有文件example.txt,内容如下:

test file.

welcome to learn python.

代码:

file = open('file/example.txt', 'r')

text = file.read()

file.close()

print(text)

输出:

test file.

welcome to learn python.

代码讲解

  • open('example.txt', 'r'):以只读模式打开指定文件
  • file.read():一次性读取文件全部内容
  • file.close():手动关闭文件,必须执行,否则会占用资源

推荐写法(with 语句)

with open('file/example.txt', 'r') as file:

text = file.read()

print(text)

输出:

test file.

welcome to learn python.

with 语句作用

with 是 Python 的上下文管理器 ,无论代码是否报错,都会在代码块结束后自动关闭文件,安全且简洁。

as file

  • as:把打开后的文件对象 赋值给变量 file
  • file:你可以自定义名称,用来操作文件
  • with 代码块内可以正常读写
  • 代码块结束后,文件自动关闭

二、文件的读取与写入

Python 支持三种主流文件读取方式:读取全部内容、逐行读取、读取所有行至列表。

  • file.read():读取整个文件全部内容
  • for line in file逐行遍历读取文件内容
  • file.readlines():读取所有行,存入列表
1. 读取整个文件 read ()

一次性加载文件全部内容,适合小文件。

with open('file/example.txt', 'r') as file:

text = file.read()

print(text)

代码解析

  1. with open('file/example.txt', 'r') as file:以只读模式打开文件,自动关闭资源
  2. file.read():读取文件全部内容,赋值给变量 text
  3. print(text):输出完整的文件内容
2. 逐行读取文件 for 循环

逐行迭代读取,节省内存,适合大文件、日志文件。

with open('file/example.txt', 'r') as file:

print("file text:")

for line in file:

print(line, end='')

输出:

file text:

test file.

welcome to learn python.

代码解析

  • for line in file:循环遍历文件的每一行数据
  • end='' 作用:
    • 默认 print() 会自带换行符,而文件每行本身自带换行,直接打印会出现多余空行
    • end='' 取消 print 默认换行,完全保留文件原始排版格式
3. 读取所有行到列表 readlines ()

将文件每一行作为列表元素存储,方便对单行数据单独操作。

with open('file/example.txt', 'r') as file:

lines = file.readlines()

print(lines)

输出:

'test file.\\n', 'welcome to learn python.'

  • file.readlines():读取文件所有行,返回一个行数据列表

三种读取方式区别与适用场景

1. read () 读取全部内容
  • 优点:代码简洁,直接获取完整文本,方便整体处理
  • 缺点:一次性加载全部内容,大文件会占用大量内存
  • 适用场景:文件体积小、需要整体分析、整体修改文件内容
2. for line in file:逐行读取文件内容
  • 优点
    • 内存友好,适合处理大文件;仅当前行驻留内存,避免一次性加载全量数据。
    • 文件对象为可迭代器,语法简洁,天然支持流式处理。
  • 缺点
    • 无法随机访问(如跳转到第100行),只能顺序遍历。
    • 若需多次遍历文件,需重新打开或使用 file.seek(0) 重置指针。
  • 适用场景
    • 文件体积大(如日志、CSV、大数据集),内存受限时。
    • 需对每行进行独立处理(如清洗、过滤、统计、写入新文件)。
    • 实时流处理或管道式数据处理(如配合生成器、map/filter等)。
3. file.readlines():读取全部行并返回列表
  • 优点
    • 支持随机访问(通过索引 lines[i] 快速获取任意行)。
    • 可多次遍历、重复使用,便于复杂分析(如交叉比对、排序、分组)。
    • 代码逻辑清晰,适合小规模数据的批量操作。
  • 缺点
    • 一次性将整个文件载入内存,对大文件易引发 MemoryError
    • 占用内存约为文件大小的 1.5--2 倍(因字符串对象开销及列表结构)。
  • 适用场景
    • 文件较小(如 < 100 MB,具体取决于可用内存)。
    • 需要频繁访问不同行(如查找特定关键词所在行号、构建索引)。
    • 数据需整体预处理后再分析(如解析配置文件、小型JSON/CSV转换)。

写入文件基础方法

文件写入分为覆盖写入和追加写入,常用两个方法:

  • file.write() :写入单行内容,配合 w 模式会覆盖原有内容
  • file.writelines():批量写入多行内容(支持列表、字符串)
覆盖写入文件(w 模式)

使用 w 写入模式 打开文件,会直接清空文件原有内容,写入新数据。

with open('file/example.txt', 'w') as file:

file.write('hello world\n')

with open('file/example.txt', 'r') as file:

text = file.read()

print(text)

输出:hello world

代码解析

  • with open('example.txt', 'w') as file :以写入模式打开文件,覆盖原有全部内容,文件不存在则自动创建。

  • file.write("Hello, World!\n") :向文件中写入指定字符串,\n 代表换行。

追加写入文件(a 模式)

with open('file/example.txt', 'a') as file:

file.write("666666.\n") # 追加新行到文件末尾

重新读取文件,查看追加后的效果

with open('file/example.txt', 'r') as file:

text = file.read()

print(text)

输出:

hello world

代码解析

  • with open('example.txt', 'a') as file 以追加模式打开文件,保留原内容,在末尾续写。

  • **file.write():**在文件末尾追加一行新内容。

一次性写入多行内容(writelines)

如果需要批量写入多行数据,可以将内容存入列表,使用 writelines() 一次性写入。

lines = ["line1","line2","line3"]

with open('file/example.txt', 'w') as file:

file.writelines(line + "\n" for line in lines)

重新读取文件,查看追加后的效果

with open('file/example.txt', 'r') as file:

text = file.read()

print(text)

输出:

line1

line2

line3

代码解析

  • 将所有需要写入的内容存入列表,每行末尾需要手动添加 \n 换行符。

  • file.writelines(lines):遍历列表,将所有元素批量写入文件。

写入模式核心区别总结

  • w 模式:覆盖写入,清空旧内容、写入新内容

  • a 模式:追加写入,保留旧内容、末尾加新内容

  • write():写入单个字符串

  • writelines():批量写入列表多行字符串

三、文件和目录管理

理论

Python 的 os 和 shutil 模块提供了文件和目录的管理功能,包括创建、删除、重命名文件和目录等。

案例

import os

with open('file/old_name.txt', 'w') as file:

file.write('renamed\n')

os.rename('file/old_name.txt', 'file/new_name.txt')

if os.path.exists('file/new_name.txt'):

print("File renamed successfully.")

else:

print("File not found.")

输出:

File renamed successfully.

删除文件:

import os

with open('file/delete.txt', 'w') as file:

file.write('delete\n')

os.remove('file/delete.txt')

if os.path.exists('file/delete.txt'):

print("File not found.")

else:

print("File deleted successfully.")

输出:

File deleted successfully.

删除目录

import os

os.makedirs('file/my_directory')

os.rmdir('file/my_directory')

if not os.path.exists('file/my_directory'):

print("Directory deleted successfully.")

else:

print("Directory not found.")

复制文件

import os

import shutil

with open('file/source_file.txt', 'w') as file:

file.write('copy\n')

shutil.copy('file/source_file.txt', 'file/destination_file.txt')

if os.path.exists('file/destination_file.txt'):

print("File copied successfully.")

else:

print("File not found.")

移动文件

import os

import shutil

with open('file/move.txt', 'w') as file:

file.write('move\n')

shutil.move('file/move.txt', 'file/moved.txt')

if os.path.exists('file/moved.txt'):

print("File moved successfully.")

else:

print("File not found.")

处理大文件

处理大文件时,直接将整个文件读入内存可能会导致内存不足或程序变得非常慢。因此,逐块读取文件内容是一种更有效的方式,这样可以逐步处理文件内容,而不是一次性加载整个文件。这种方法特别适合处理大型日志文件、大型数据文件等。

逐块读取的主要优点包括:

节省内存:只需将文件的一部分加载到内存中,而不是整个文件。

提高性能:可以立即开始处理文件的一部分数据,而不是等待整个文件加载完成。

import os

chunk_size = 1024

with open('file/source_file.txt', 'w') as source_file:

source_file.write('A' * chunk_size * 10)

with open('file/source_file.txt', 'r') as source_file:

while True:

chunk = source_file.read(chunk_size)

if not chunk:

break

print(chunk[:100])

代码解释:

1. 创建模拟大文件
  • 打开/创建文件 :使用 with open('large_file.txt', 'w') as file: 以文本写入模式打开文件。若文件不存在则自动创建,with 语句确保操作完成后文件被安全关闭。
  • 写入测试数据 :通过 file.write("A" * 1024 * 1024) 向文件中写入 1 MB(1,048,576 个字符)的连续字符 "A",用于模拟一个需要分块处理的大文件。
2. 分块读取核心流程
  • 打开待读文件 :使用 with open('large_file.txt', 'r') as file: 以文本只读模式打开目标文件。
  • 构建读取循环 :采用 while True: 无限循环持续读取数据块,这是 Python 中处理流式数据的标准范式。
  • 按块读取数据 :在循环体内执行 chunk = file.read(chunk_size),每次从当前文件指针位置读取固定大小(本例为 1 KB)的数据。
  • 检测文件末尾 :通过 if not chunk: break 判断读取结果。当 read() 到达文件末尾时返回空字符串 '',其布尔值为 False,触发 break 安全退出循环。
  • 采样打印预览 :执行 print(chunk[:100]) 仅输出当前数据块的前 100 个字符。此举旨在验证数据内容的正确性,同时避免将大量数据直接输出到控制台导致性能卡顿或信息过载。
3. ⚠️ 关键技术注解

文本模式 vs 二进制模式的区别

当前代码使用 'r'(文本模式),此时 file.read(chunk_size) 读取的单位是 字符数 而非字节数。对于纯 ASCII 字符(如 "A"),1 字符 = 1 字节,两者等价;但若文件包含 UTF-8 编码的中文等多字节字符,1024 个字符实际占用的字节数会远超 1024 字节。若需严格按字节分块(如处理图片、视频或网络流),应改用 'rb' 二进制模式。

实际案例:

你需要备份某个目录中的所有文件到另一个备份目录。每次备份时,创建一个新的备份文件夹,以便将文件按时间戳命名。

import os

import shutil

from datetime import datetime

src_dir = 'file/source'

dest_dir = 'file/backup'

if not os.path.exists(src_dir):

os.makedirs(src_dir)

os.makedirs(os.path.join(src_dir, 'subdir1'), exist_ok=True)

os.makedirs(os.path.join(src_dir, 'subdir2'), exist_ok=True)

with open(os.path.join(src_dir, 'file1.txt'), 'w') as f:

f.write('This is file 1.')

with open(os.path.join(src_dir, 'subdir1', 'file2.txt'), 'w') as f:

f.write('This is file 2.')

with open(os.path.join(src_dir, 'subdir2', 'file3.txt'), 'w') as f:

f.write('This is file 3.')

if not os.path.exists(dest_dir):

os.makedirs(dest_dir)

timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')

backup_dir = os.path.join(dest_dir, f'backup_{timestamp}')

os.makedirs(backup_dir)

for item in os.listdir(src_dir):

s = os.path.join(src_dir, item)

d = os.path.join(backup_dir, item)

if os.path.isdir(s):

shutil.copytree(s, d,dirs_exist_ok=True,copy_function=shutil.copy2)

else:

shutil.copy2(s, d)

print(f'Backup of {src_dir} created in {backup_dir}')

代码解释:

  1. if os.path.isdir(s):

意思:判断 s 是不是文件夹

  • s = 源路径(比如 file/source/subdir1
  • 如果是文件夹 → 执行 copytree
  • 如果是文件 → 执行 copy2

  1. shutil.copytree(...)

作用:复制 整个文件夹 + 里面所有内容 (文件 + 子文件夹 + 全部内容,一键复制)

里面的参数:

s → 源文件夹(从哪复制)

d → 目标文件夹(复制到哪)

dirs_exist_ok=True

意思:如果目标文件夹已经存在,不报错,直接覆盖 / 合并

  • 默认是 False,如果文件夹已存在会直接崩溃
  • 你写 =True 就是告诉程序: "文件夹存在没关系,我允许覆盖"

copy_function=shutil.copy2

意思:复制文件时,用 copy2 这个方法

  1. shutil.copy2(s, d)

作用:复制 单个文件

copy2 比普通复制更强:

  • 不仅复制内容
  • 还保留文件的:创建时间、修改时间、权限
清除过期日志文件

log_path = 'file/logs'

if not os.path.exists(log_path):

os.makedirs(log_path)

days_list = [15, 30, 45, 60]

for days in days_list:

file_name = f"log_{days}days.txt"

file_path = os.path.join(log_path, file_name)

with open(file_path, 'w') as file:

file.write(f"This is the log file for {days} days.\n")

past_time = datetime.now() - timedelta(days=days)

past_timestamp = past_time.timestamp()

os.utime(file_path, (past_timestamp, past_timestamp))

print(f"Log files created in {log_path}")

days = 30

cutoff = datetime.now() - timedelta(days=days)

for file_name in os.listdir(log_path):

file_path = os.path.join(log_path, file_name)

if os.path.isfile(file_path):

file_time = os.path.getmtime(file_path)

file_datetime = datetime.fromtimestamp(file_time)

if file_datetime < cutoff:

os.remove(file_path)

删除了30天以上的日志

批量重命名文件

"""

file = open('file/example.txt', 'r')

text = file.read()

file.close()

print(text)

"""

"""

with open('file/example.txt', 'r') as file:

text = file.read()

print(text)

"""

"""

with open('file/example.txt', 'r') as file:

print("file text:")

for line in file:

print(line, end='')

"""

"""

with open('file/example.txt', 'r') as file:

lines = file.readlines()

print(lines)

with open('file/example.txt', 'r') as file:

lines = file.readlines() # 将文件的每一行读入列表

print("File Content:")

for line in lines:

print(line, end='')

"""

"""

with open('file/example.txt', 'w') as file:

file.write('hello world\n')

with open('file/example.txt', 'r') as file:

text = file.read()

print(text)

追加数据到文件末尾

with open('file/example.txt', 'a') as file:

file.write("666666.\n") # 追加新行到文件末尾

重新读取文件,查看追加后的效果

with open('file/example.txt', 'r') as file:

text = file.read()

print(text)

lines = ["line1","line2","line3"]

with open('file/example.txt', 'w') as file:

file.writelines(line + "\n" for line in lines)

重新读取文件,查看追加后的效果

with open('file/example.txt', 'r') as file:

text = file.read()

print(text)

"""

import os

import shutil

from datetime import datetime, timedelta

"""

src_dir = 'file/source'

dest_dir = 'file/backup'

if not os.path.exists(src_dir):

os.makedirs(src_dir)

os.makedirs(os.path.join(src_dir, 'subdir1'), exist_ok=True)

os.makedirs(os.path.join(src_dir, 'subdir2'), exist_ok=True)

with open(os.path.join(src_dir, 'file1.txt'), 'w') as f:

f.write('This is file 1.')

with open(os.path.join(src_dir, 'subdir1', 'file2.txt'), 'w') as f:

f.write('This is file 2.')

with open(os.path.join(src_dir, 'subdir2', 'file3.txt'), 'w') as f:

f.write('This is file 3.')

if not os.path.exists(dest_dir):

os.makedirs(dest_dir)

timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')

backup_dir = os.path.join(dest_dir, f'backup_{timestamp}')

os.makedirs(backup_dir)

for item in os.listdir(src_dir):

s = os.path.join(src_dir, item)

d = os.path.join(backup_dir, item)

if os.path.isdir(s):

shutil.copytree(s, d,dirs_exist_ok=True,copy_function=shutil.copy2)

else:

shutil.copy2(s, d)

print(f'Backup of {src_dir} created in {backup_dir}')

"""

"""

log_path = 'file/logs'

if not os.path.exists(log_path):

os.makedirs(log_path)

days_list = [15, 30, 45, 60]

for days in days_list:

file_name = f"log_{days}days.txt"

file_path = os.path.join(log_path, file_name)

with open(file_path, 'w') as file:

file.write(f"This is the log file for {days} days.\n")

past_time = datetime.now() - timedelta(days=days)

past_timestamp = past_time.timestamp()

os.utime(file_path, (past_timestamp, past_timestamp))

print(f"Log files created in {log_path}")

days = 30

cutoff = datetime.now() - timedelta(days=days)

for file_name in os.listdir(log_path):

file_path = os.path.join(log_path, file_name)

if os.path.isfile(file_path):

file_time = os.path.getmtime(file_path)

file_datetime = datetime.fromtimestamp(file_time)

if file_datetime < cutoff:

os.remove(file_path)

"""

log_path = 'file/logs'

old_ext= '.txt'

new_ext = '.log'

if not os.path.exists(log_path):

os.makedirs(log_path)

days_list = [15, 30, 45, 60]

for days in days_list:

file_name = f"log_{days}days.txt"

file_path = os.path.join(log_path, file_name)

with open(file_path, 'w') as file:

file.write(f"This is the log file for {days} days.\n")

past_time = datetime.now() - timedelta(days=days)

past_timestamp = past_time.timestamp()

os.utime(file_path, (past_timestamp, past_timestamp))

print(f"Log files created in {log_path}")

for file_name in os.listdir(log_path):

if file_name.endswith(old_ext):

new_file_name = os.path.splitext(file_name)[0] + new_ext

new_file_path = os.path.join(log_path, new_file_name)

old_file_path = os.path.join(log_path, file_name)

os.rename(old_file_path, new_file_path)

相关推荐
nbsaas-boot17 小时前
Drools 规则引擎实战:原理、规则语法、数据库动态规则与企业级玩法
java·数据库·python
I Promise3418 小时前
C++ 单例模式超详细讲解
开发语言·c++·单例模式
之歆18 小时前
Day17_JavaScript高级核心垃圾回收执行上下文闭包完全指南(上)
开发语言·javascript·ecmascript
weixin_5500831518 小时前
基于Python的豆瓣电影数据爬取与可视化分析
开发语言·python
Lenyiin18 小时前
第5篇_Python文件操作与异常处理:程序与外界交互的桥梁
python·oracle·交互
xyq202418 小时前
jQuery Mobile Data 属性详解
开发语言
YOLO数据集集合18 小时前
光伏板缺陷检测数据集|红外可见光双模态|无人机光伏巡检|智慧电网光伏识别数据集
开发语言·yolo·目标检测·无人机
AI人工智能+电脑小能手18 小时前
【大白话说Java面试题 第74题】【Mysql篇】第4题:InnoDB 和 MyISAM 的数据文件存储区别?
java·开发语言·mysql·面试
qq_25183645718 小时前
基于java Web快乐岛儿童网站设计与实现
java·开发语言·前端