python进阶之文件处理

Python 进阶文件操作与文件路径完全指南

在 Python 开发中,文件操作是基础且核心的技能,从简单的读写文件到复杂的目录遍历、路径处理、大文件分块处理,几乎贯穿所有项目场景(如数据处理、日志分析、配置管理等)。本文将从「文件操作进阶」和「文件路径处理」两大维度,结合实战案例详细拆解 Python 文件操作的核心技巧,帮助开发者彻底掌握这一必备技能。

一、文件操作进阶:不止于基础读写

Python 基础文件操作(open()函数)仅能满足简单需求,实际开发中更需要处理大文件、二进制文件、上下文管理、权限控制等复杂场景。

1. 上下文管理器的高级用法

基础的with open()语法大家都熟悉,但它的进阶用法能大幅提升代码安全性和效率:

复制代码
\# 1. 同时操作多个文件(读写关联)

with open("source.txt", "r", encoding="utf-8") as src, open("target.txt", "w", encoding="utf-8") as dst:

    \# 一行一行复制(避免加载整个文件到内存)

    for line in src:

        dst.write(line.strip() + "\n")  # 处理后写入目标文件

\# 2. 二进制文件操作(图片、视频、压缩包等)

with open("image.png", "rb") as f\_in, open("image\_copy.png", "wb") as f\_out:

    \# 分块读取(适合大文件,避免内存溢出)

    chunk\_size = 1024 \* 1024  # 1MB/块

    while chunk := f\_in.read(chunk\_size):

        f\_out.write(chunk)

\# 3. 自定义上下文管理器(文件操作增强)

class FileLogger:

    def \_\_init\_\_(self, filename, mode="a", encoding="utf-8"):

        self.filename = filename

        self.mode = mode

        self.encoding = encoding

    def \_\_enter\_\_(self):

        self.file = open(self.filename, self.mode, encoding=self.encoding)

        return self.file

    def \_\_exit\_\_(self, exc\_type, exc\_val, exc\_tb):

        self.file.close()

        \# 捕获异常并记录

        if exc\_type:

            with open("error.log", "a", encoding="utf-8") as err\_f:

                err\_f.write(f"Error: {exc\_val} in {self.filename}\n")

        return True  # 抑制异常传播

\# 使用自定义上下文管理器

with FileLogger("app.log") as logger:

    logger.write("Program started at 2025-01-01\n")

    \# 模拟异常

    1 / 0  # 异常会被捕获并记录到error.log,程序不崩溃
1.1 open
1.2 close
1.3 with语句
python 复制代码
with open("text.txt",'r',encoding = 'utf-8')as f:
		print(f.encoding)
print(f.close)

2. 大文件处理技巧(避免内存溢出)

当处理 GB 级大文件时,直接read()会将文件全部加载到内存,导致程序崩溃。核心思路是「分块处理」或「逐行读取」:

复制代码
\# 方案1:逐行读取(适合文本文件)

def process\_large\_text\_file(filepath, output\_path):

    with open(filepath, "r", encoding="utf-8") as f\_in, open(output\_path, "w", encoding="utf-8") as f\_out:

        for line\_num, line in enumerate(f\_in, 1):

            \# 处理逻辑:过滤空行并添加行号

            if line.strip():

                f\_out.write(f"\[{line\_num}] {line}")

\# 方案2:分块读取(适合二进制/超大文本文件)

def split\_large\_file(filepath, chunk\_size=1024\*1024\*10):  # 10MB/块

    with open(filepath, "rb") as f:

        chunk\_idx = 1

        while chunk := f.read(chunk\_size):

            with open(f"{filepath}\_part{chunk\_idx}", "wb") as chunk\_f:

                chunk\_f.write(chunk)

            chunk\_idx += 1

\# 方案3:使用生成器读取(内存占用最低)

def read\_large\_file\_generator(filepath, chunk\_size=1024\*1024):

    with open(filepath, "rb") as f:

        while chunk := f.read(chunk\_size):

            yield chunk

\# 使用生成器处理

for chunk in read\_large\_file\_generator("large\_data.csv"):

    \# 处理每个块(如解析CSV、统计数据等)

    process\_chunk(chunk)

3. 文件权限与属性管理

在 Linux/Mac 系统中,文件权限控制至关重要,Python 通过os模块实现权限管理:

复制代码
import os

import stat

\# 1. 获取文件权限(八进制表示)

file\_path = "test.txt"

file\_stat = os.stat(file\_path)

print(f"文件权限(八进制): {oct(file\_stat.st\_mode)\[-3:]}")  # 输出如 644

\# 2. 修改文件权限(chmod)

os.chmod(file\_path, stat.S\_IRWXU)  # 所有者可读可写可执行(700)

os.chmod(file\_path, 0o644)  # 等价写法:所有者读写,其他只读

\# 3. 获取文件属性(大小、创建时间、修改时间)

print(f"文件大小: {file\_stat.st\_size} 字节")

print(f"创建时间: {pd.to\_datetime(file\_stat.st\_ctime, unit='s')}")  # 需要pandas

print(f"最后修改时间: {pd.to\_datetime(file\_stat.st\_mtime, unit='s')}")

\# 4. 批量修改目录下文件权限

def set\_dir\_file\_permissions(dir\_path, perm=0o644):

    for root, dirs, files in os.walk(dir\_path):

        \# 修改目录权限(需要执行权限才能进入)

        for dir\_name in dirs:

            dir\_full\_path = os.path.join(root, dir\_name)

            os.chmod(dir\_full\_path, 0o755)

        \# 修改文件权限

        for file\_name in files:

            file\_full\_path = os.path.join(root, file\_name)

            os.chmod(file\_full\_path, perm)

二、文件路径处理:从 os.path 到 pathlib

文件路径处理是跨平台开发的痛点(Windows 用\,Linux/Mac 用/),Python 提供os.path(传统)和pathlib(Python3.4 + 推荐)两大模块,后者支持面向对象编程,更简洁易用。

1. os.path 模块:传统路径处理

os.path是 Python2 时代的经典模块,通过函数式编程处理路径,兼容性好:

复制代码
import os

\# 1. 路径拼接(避免手动拼接导致的跨平台问题)

base\_dir = "/home/user/project"

file\_name = "data.csv"

full\_path = os.path.join(base\_dir, "data", file\_name)

print(full\_path)  # Linux输出: /home/user/project/data/data.csv

\# 2. 路径拆解

print(os.path.dirname(full\_path))  # 获取目录: /home/user/project/data

print(os.path.basename(full\_path))  # 获取文件名: data.csv

print(os.path.splitext(full\_path))  # 拆分文件名和后缀: ("data", ".csv")

\# 3. 路径判断

print(os.path.exists(full\_path))  # 是否存在

print(os.path.isfile(full\_path))  # 是否为文件

print(os.path.isdir(full\_path))   # 是否为目录

print(os.path.isabs(full\_path))   # 是否为绝对路径

\# 4. 绝对路径与相对路径转换

relative\_path = "../data/data.csv"

print(os.path.abspath(relative\_path))  # 转为绝对路径

print(os.path.relpath(full\_path, "/home/user"))  # 转为相对路径: project/data/data.csv

\# 5. 目录操作

os.makedirs("new\_dir/sub\_dir", exist\_ok=True)  # 递归创建目录(exist\_ok=True避免已存在报错)

os.removedirs("new\_dir/sub\_dir")  # 递归删除空目录

os.rmdir("new\_dir")  # 删除空目录(非空则报错)

2. pathlib 模块:面向对象的路径处理(推荐)

pathlib是 Python3.4 + 引入的新模块,将路径视为对象,支持链式调用,代码更简洁:

复制代码
from pathlib import Path

\# 1. 创建路径对象

base\_dir = Path("/home/user/project")

file\_path = base\_dir / "data" / "data.csv"  # 链式拼接(跨平台自动适配分隔符)

print(file\_path)  # 输出: /home/user/project/data/data.csv

\# 2. 路径属性与方法(面向对象设计)

print(file\_path.parent)  # 父目录: /home/user/project/data

print(file\_path.name)    # 文件名: data.csv

print(file\_path.stem)    # 文件名(无后缀): data

print(file\_path.suffix)  # 文件后缀: .csv

print(file\_path.absolute())  # 绝对路径

print(file\_path.resolve())   # 解析符号链接后的绝对路径

\# 3. 路径判断(比os.path更直观)

print(file\_path.exists())  # 是否存在

print(file\_path.is\_file())  # 是否为文件

print(file\_path.is\_dir())   # 是否为目录

print(file\_path.is\_absolute())  # 是否为绝对路径

\# 4. 目录操作

new\_dir = Path("new\_dir/sub\_dir")

new\_dir.mkdir(parents=True, exist\_ok=True)  # 递归创建目录(parents=True等价于os.makedirs)

new\_dir.rmdir()  # 删除空目录

file\_path.unlink(missing\_ok=True)  # 删除文件(missing\_ok=True避免文件不存在报错)

\# 5. 批量遍历目录(glob模式)

\# 查找目录下所有.csv文件(递归)

csv\_files = base\_dir.glob("\*\*/\*.csv")

for csv\_file in csv\_files:

    print(csv\_file)

\# 查找特定文件名的文件

log\_files = base\_dir.glob("\*.log")  # 非递归查找

3. 两大模块对比与选型建议

特性 os.path(传统) pathlib(现代)
编程风格 函数式(如 os.path.join) 面向对象(如 path / "a")
代码简洁度 较低(多函数嵌套) 高(链式调用)
跨平台兼容性 好(需手动处理分隔符) 优秀(自动适配分隔符)
目录遍历 需配合 os.walk () 内置 glob ()/rglob ()
学习成本 低(函数简单) 中(面向对象思想)
推荐场景 Python2 兼容项目 Python3.4 + 新项目

选型建议 :新项目优先使用pathlib,代码更简洁易维护;老项目或需兼容 Python2 时使用os.path

4. 读取文件(3种)

4.1 read(n):读取指定的字符(字节)

语法:文件对象.read(n),n为读取的字符数(文本模式)或者字节数(二进制模式)
省略n读取整个文件

python 复制代码
with open("test.txt",'r',encoding = 'utf-8') as f:
	 data = f.read(n)
print(data)
4.2 readline() 逐行读取

每次读取一行,文件指针自动移动到下一行,适合大文件(避免占用很多内存)。

python 复制代码
with open("test.txt",'r',encoding = 'utf-8') as f:
	 line1 = f.readline()
	 line2 = f.readline()
print(line1,end = '')
print(line2)
4.3 readlines():读取所有行(返回列表)

把文件所有行作为表元素返回,每行是一个字符串,适合小文件。返回列表。

python 复制代码
with open("test.txt",'r',encoding = 'utf-8') as f:
	 lines = f.readlines()
print(lines)

5. write()

5.1 w模式

会覆盖

5.2 a模式

追加模式(a),文件不存在则创建文件,文件存在的基础上会追加在文件末尾,不会覆盖内容

python 复制代码
with open('test.txt','a') as f:
	 f.write("\nbingbing")

三、实战案例:文件操作综合应用

案例 1:递归遍历目录并统计文件类型

需求:遍历指定目录,统计所有文件类型(后缀)的数量,生成统计报告。

复制代码
from pathlib import Path

from collections import defaultdict

def count\_file\_types(dir\_path):

    dir\_obj = Path(dir\_path)

    if not dir\_obj.is\_dir():

        raise ValueError(f"{dir\_path} 不是有效目录")

    

    file\_count = defaultdict(int)

    

    \# 递归遍历所有文件

    for file in dir\_obj.rglob("\*"):

        if file.is\_file():

            \# 获取文件后缀(无后缀则记为"无后缀")

            suffix = file.suffix.lower() if file.suffix else "无后缀"

            file\_count\[suffix] += 1

    

    \# 生成统计报告

    with open("file\_type\_report.txt", "w", encoding="utf-8") as f:

        f.write(f"目录文件类型统计报告:{dir\_path}\n")

        f.write(f"总文件数:{sum(file\_count.values())}\n")

        f.write("-" \* 30 + "\n")

        for suffix, count in sorted(file\_count.items()):

            f.write(f"{suffix}: {count} 个\n")

    

    return file\_count

\# 调用函数

result = count\_file\_types("/home/user/project")

print(result)  # 输出如: {'.csv': 10, '.log': 5, '无后缀': 3}

案例 2:批量重命名文件(按规则格式化)

需求:将目录下所有图片文件按「日期_序号。后缀」格式重命名(如 20250101_001.jpg)。

复制代码
from pathlib import Path

from datetime import datetime

def batch\_rename\_files(dir\_path, file\_suffixes=\[".jpg", ".png", ".jpeg"]):

    dir\_obj = Path(dir\_path)

    if not dir\_obj.is\_dir():

        raise ValueError(f"{dir\_path} 不是有效目录")

    

    \# 获取当前日期(格式:YYYYMMDD)

    date\_str = datetime.now().strftime("%Y%m%d")

    file\_idx = 1

    

    \# 遍历目录下指定后缀的文件

    for file in dir\_obj.iterdir():

        if file.is\_file() and file.suffix.lower() in file\_suffixes:

            \# 构建新文件名

            new\_file\_name = f"{date\_str}\_{file\_idx:03d}{file.suffix}"

            new\_file\_path = dir\_obj / new\_file\_name

            

            \# 重命名(避免覆盖已存在文件)

            if new\_file\_path.exists():

                print(f"跳过:{new\_file\_name} 已存在")

                file\_idx += 1

                continue

            

            file.rename(new\_file\_path)

            print(f"重命名:{file.name} -> {new\_file\_name}")

            file\_idx += 1

\# 调用函数

batch\_rename\_files("/home/user/photos")

案例 3:跨平台路径兼容的配置文件读写

需求:创建一个配置文件管理器,支持跨平台路径存储和配置读写。

复制代码
from pathlib import Path

import json

class ConfigManager:

    def \_\_init\_\_(self, config\_name="config.json"):

        \# 跨平台兼容:用户主目录下创建配置文件

        self.config\_path = Path.home() / ".my\_app" / config\_name

        \# 确保配置目录存在

        self.config\_path.parent.mkdir(exist\_ok=True)

    

    def read\_config(self):

        \# 读取配置(无文件则返回默认配置)

        if self.config\_path.exists():

            with open(self.config\_path, "r", encoding="utf-8") as f:

                return json.load(f)

        return {"theme": "light", "language": "zh-CN"}

    

    def write\_config(self, config\_dict):

        \# 写入配置(合并现有配置)

        existing\_config = self.read\_config()

        existing\_config.update(config\_dict)

        with open(self.config\_path, "w", encoding="utf-8") as f:

            json.dump(existing\_config, f, ensure\_ascii=False, indent=2)

    

    def get\_config(self, key, default=None):

        \# 获取指定配置项

        config = self.read\_config()

        return config.get(key, default)

\# 使用配置管理器

config = ConfigManager()

config.write\_config({"theme": "dark", "font\_size": 14})

print(config.get\_config("theme"))  # 输出: dark

print(config.read\_config())  # 输出: {"theme": "dark", "language": "zh-CN", "font\_size": 14}

四、避坑指南与最佳实践

1. 常见坑点

  • 跨平台路径分隔符 :手动拼接路径(如base_dir + "/data")在 Windows 上会报错,务必使用os.path.join()pathlib/运算符。

  • 文件编码问题 :读取中文文件时未指定encoding="utf-8",导致UnicodeDecodeError;建议所有文本文件操作都显式指定编码。

  • 大文件内存溢出 :直接使用read()读取 GB 级文件,导致程序崩溃;采用分块读取或生成器。

  • 目录删除报错os.rmdir()只能删除空目录,删除非空目录需先删除文件(可使用shutil.rmtree())。

  • 权限不足 :修改文件 / 目录权限时,当前用户无权限导致PermissionError;需确保运行环境有足够权限(如 Linux 用sudo)。

2. 最佳实践

  • 优先使用 pathlib :Python3.4 + 项目推荐使用pathlib,代码更简洁、跨平台兼容性更好。

  • 使用上下文管理器 :始终用with open()操作文件,自动关闭文件句柄,避免资源泄露。

  • 显式指定编码 :文本文件操作时,显式设置encoding="utf-8",避免编码不一致问题。

  • 分块处理大文件:处理超大文件时,采用分块读取或逐行读取,控制内存占用。

  • 异常处理 :文件操作可能出现FileNotFoundErrorPermissionError等异常,需添加异常捕获:

    try:

    with open("data.csv", "r", encoding="utf-8") as f:

    data = f.read()

    except FileNotFoundError:

    print("文件不存在,请检查路径")

    except PermissionError:

    print("权限不足,无法读取文件")

    except Exception as e:

    print(f"读取文件失败:{str(e)}")

五、总结

Python 文件操作与路径处理是开发必备技能,本文从「进阶文件操作」(上下文管理、大文件处理、权限控制)和「路径处理」(os.path、pathlib)两大核心模块,结合实战案例详细讲解了关键技巧。掌握这些内容后,能轻松应对数据处理、日志分析、配置管理等场景中的文件相关需求。

核心要点回顾:

  1. 复杂文件操作优先使用「上下文管理器 + 分块读取」,兼顾安全性和效率;

  2. 路径处理推荐使用pathlib,面向对象设计更简洁,跨平台兼容性更好;

  3. 实战中需注意异常处理、编码设置、权限控制,避免常见坑点;

  4. 批量文件处理(遍历、重命名、统计)可结合glob模式和递归遍历实现。

希望本文能帮助你彻底掌握 Python 文件操作进阶技巧,提升开发效率!如果有具体场景需求(如 FTP 文件操作、压缩文件处理),可以留言交流~

(注:文档部分内容可能由 AI 生成)

相关推荐
星月心城2 小时前
八股文-JavaScript(第一天)
开发语言·前端·javascript
Thomas_YXQ2 小时前
Unity3D的委托和事件的用法详解
java·开发语言
编程小Y2 小时前
Bash 替换机制
开发语言·chrome·bash
我要学脑机2 小时前
一个图谱映射到功能网络yeo7或17的解决方案
开发语言·网络·php
前端程序猿之路2 小时前
模型应用开发的基础工具与原理之Web 框架
前端·python·语言模型·学习方法·web·ai编程·改行学it
坐吃山猪2 小时前
Python之PDF小工具
开发语言·python·pdf
代码栈上的思考2 小时前
MyBatis——动态SQL讲解
java·开发语言·数据库
achi0102 小时前
从 0 到 1 掌握 Gunicorn:让 Python Web 应用飞起来的 WSGI 服务器
python·flask·性能调优·容器化·gunicorn·wsgi·并发模型