Python Day20 os模块 和 文件操作 及 例题分析

一、os 模块(操作系统相关操作)

1. 基础信息获取
  • os.name:返回操作系统标识
    • nt:代表 Windows 系统
    • posix:代表 Unix/Linux 系统
  • os.curdir:返回当前目录符号(.
  • os.environ:获取系统环境变量(如os.environ["PATH"]查看 PATH 变量)
  • os.chdir(path):切换当前工作目录
2. 目录操作(创建 / 删除)
函数 功能 注意事项
os.mkdir(path) 创建单个目录 父目录必须存在;目录已存在则报错
os.makedirs(path) 递归创建目录(含不存在的父目录) 目标目录已存在则报错
os.rmdir(path) 删除空目录 目录非空则报错
os.removedirs(path) 递归删除路径中所有空目录(从子到父,遇到非空目录则停止)
os.listdir(path) 获取指定路径下的所有文件 / 目录名称,返回列表
3. 路径分隔符处理
  • Windows 用\,Linux 用/
  • 表示路径时避免转义问题:
    • r前缀(如r"D:\test"
    • \\替代\(如"D:\\test"
    • 统一用/(跨平台兼容,如"D:/test"

二、os.path 模块(路径处理)

1. 路径判断
  • os.path.exists(path):判断路径是否存在
  • os.path.isfile(path):判断路径是否为文件
  • os.path.isdir(path):判断路径是否为目录
  • os.path.isabs(path):判断是否为绝对路径
2. 路径解析
  • os.path.dirname(path):获取父级路径(如"D:/abc/1.txt"返回"D:/abc"
  • os.path.basename(path):获取文件名 / 目录名(如"D:/abc/1.txt"返回"1.txt"
  • os.path.join(parent, name):拼接路径
    • name是绝对路径,则直接返回name(忽略parent
3. 路径转换与信息
  • os.path.abspath(path):获取绝对路径
  • os.path.getsize(path):获取文件大小(字节),目录默认返回 4096
  • 时间相关(返回时间戳,需用datetime.fromtimestamp()转换):
    • os.path.getctime(path):创建时间
    • os.path.getatime(path):最后访问时间
    • os.path.getmtime(path):最后修改时间

三、文件操作

1. 文件类型
  • 字符文件 :存储文本内容(如.txt,可用记事本打开)
  • 字节文件 :二进制文件(如.png.exe
2. open () 函数(核心)

用于打开文件,返回文件对象,语法:
open(path, mode, encoding)

  • path:文件路径(不可指向目录)
  • mode:操作模式(默认rt):
    • 读写模式:r(读)、w(写,覆盖)、a(追加)、x(创建新文件,存在则报错)、+(读写)
    • 数据类型:t(文本模式,字符串,需指定encoding)、b(字节模式,二进制流,不指定encoding
  • 推荐用with语句自动关闭文件:with open(...) as f: ...
3. 读取方法(文件对象方法)
方法 功能 适用场景
f.read(n) 读取n个字符 / 字节,默认读全部 小文件
f.readline() 读取一行数据 按行读取
f.readlines() 读取所有行,返回列表(每行作为元素) 行数较少的文件
f.seek(n) 将读取光标移到第n个字符 / 字节处 随机读取
4. 写入方法(文件对象方法)
方法 功能 说明
f.write(content) 写入内容(文本模式传字符串,字节模式传b"..."
f.writelines(list) 批量写入列表中的元素(需自行加换行符)
5. 大文件处理

避免一次性读取全部内容(内存溢出),循环分块读取:

复制代码
# 大字符文件
with open("large.txt", "rt", encoding="utf-8") as f:
    while (data := f.read(1000)) != "":  # 每次读1000字符
        print(data)

# 大字节文件
with open("large.png", "rb") as f:
    while (data := f.read(8 << 10)) != b"":  # 每次读8KB
        print(data)

四、目录高级操作(自定义函数)

1. 递归获取目录下所有文件
复制代码
def get_files(direction):
    """返回目录下所有文件的绝对路径(含子目录)"""
    ret = []
    for file in os.listdir(direction):
        file_path = os.path.join(direction, file)
        if os.path.isfile(file_path):
            ret.append(file_path)
        else:
            ret += get_files(file_path)  # 递归子目录
    return ret
2. 递归删除目录(含内容)
复制代码
def remove_dir(direction):
    """删除目录及所有子文件/子目录"""
    for file in os.listdir(direction):
        path = os.path.join(direction, file)
        if os.path.isfile(path):
            os.remove(path)  # 删除文件
        else:
            remove_dir(path)  # 递归删除子目录
    os.rmdir(direction)  # 最后删除空目录

五、shutil 模块(高级文件 / 目录操作)

函数 功能 注意事项
shutil.copyfile(src, dst) 拷贝文件内容(仅文件) dst若存在则覆盖
shutil.copy(src, dst) 拷贝文件(含权限),dst可为目录(自动用原文件名)
shutil.move(src, dst) 移动 / 重命名文件 / 目录 - 移动到目录:dst必须存在 - 重命名:dst需不存在
shutil.copytree(src, dst) 递归拷贝目录(含所有内容) dst必须不存在
shutil.rmtree(src) 递归删除目录及所有内容(危险!) 无需目录为空

六、绝对路径表示

  • Windows:D:/abcD:\abc(推荐用/跨平台)
  • Linux:/abc

一、文件工具类 FileUtils

封装了文件 / 目录的常用操作,提供一系列类方法处理路径、文件读写、拷贝、删除等功能。

复制代码
from typing import List, Callable
import os

class FileUtils:
    @classmethod
    def get_files(cls, path: str, predicate: Callable[[str], bool] = None) -> List[str]:
        """根据条件获取指定目录下所有满足条件的文件(非递归,仅当前目录)"""
        data = os.listdir(path)
        ret = []
        for item in data:
            file = os.path.join(path, item)
            if predicate(file):  # 满足条件的文件路径加入结果
                ret.append(file)
        return ret

    @classmethod
    def remove(cls, path: str) -> None:
        """递归删除文件或目录(支持非空目录)"""
        if os.path.isdir(path):
            # 先删除目录内所有内容
            for item in os.listdir(path):
                item_path = os.path.join(path, item)
                cls.remove(item_path)
            os.rmdir(path)  # 最后删除空目录
        else:
            os.remove(path)  # 直接删除文件

    @classmethod
    def get_parent(cls, path: str) -> str:
        """获取路径的父级目录"""
        return os.path.dirname(path)

    @classmethod
    def get_name(cls, path: str) -> str:
        """获取路径中的文件名或目录名"""
        return os.path.basename(path)

    @classmethod
    def get_size(cls, file: str) -> int:
        """获取文件大小(字节),目录默认返回4096"""
        return os.path.getsize(file)

    @classmethod
    def is_dir(cls, path: str) -> bool:
        """判断路径是否为目录"""
        return os.path.isdir(path)

    @classmethod
    def is_file(cls, path: str) -> bool:
        """判断路径是否为文件"""
        return os.path.isfile(path)

    @classmethod
    def exists(cls, path: str) -> bool:
        """判断路径是否存在"""
        return os.path.exists(path)

    @classmethod
    def get_ext(cls, file: str) -> str:
        """获取文件后缀名(不含.),无后缀返回空字符串"""
        ext = os.path.splitext(file)[1]
        return ext[1:] if ext else ''  # 去除前缀.

    @classmethod
    def copy_file_to_dir(cls, file: str, directory: str) -> None:
        """将文件拷贝到目标目录(保留原文件名)"""
        dest_path = os.path.join(directory, cls.get_name(file))
        cls.copy_file(file, dest_path)

    @classmethod
    def copy_file(cls, srcfile: str, destfile: str) -> None:
        """拷贝源文件内容到目标文件(二进制方式,支持所有文件类型)"""
        with open(srcfile, 'rb') as f, open(destfile, 'wb') as w:
            while (data := f.read(8 << 10)) != b'':  # 每次读8KB
                w.write(data)

    @classmethod
    def copy_directory(cls, src: str, dest: str) -> None:
        """递归拷贝目录(含所有子文件和子目录)"""
        # 遍历源目录内容
        for item in os.listdir(src):
            src_path = os.path.join(src, item)
            dest_path = os.path.join(dest, item)
            
            if os.path.isfile(src_path):
                cls.copy_file(src_path, dest_path)  # 拷贝文件
            else:
                # 若目标子目录不存在则创建,递归拷贝
                if not os.path.exists(dest_path):
                    os.makedirs(dest_path)
                cls.copy_directory(src_path, dest_path)

    @classmethod
    def read_to_string(cls, file: str, encoding="utf-8") -> str:
        """读取文本文件内容并返回字符串"""
        with open(file, 'rt', encoding=encoding) as f:
            return f.read()

    @classmethod
    def chunks(cls, file: str, chunk_size: int = 8192):
        """生成器:分块读取大文件(字节方式),默认每次8KB"""
        with open(file, 'rb') as f:
            while True:
                data = f.read(chunk_size)
                if not data:  # 读取完毕
                    break
                yield data

    @classmethod
    def writestr(cls, string: str, file: str, encoding="utf-8") -> None:
        """追加字符串到文本文件(若文件不存在则创建)"""
        with open(file, 'a', encoding=encoding) as f:
            f.write(string)

二、递归函数(文件 / 目录操作)

1. 递归获取所有文件路径

python

运行

复制代码
def list_files(path: str) -> List[str]:
    """递归获取指定目录下所有文件的绝对路径(含所有子目录)"""
    result = []
    for item in os.listdir(path):
        item_path = os.path.join(path, item)
        if os.path.isfile(item_path):
            result.append(item_path)  # 是文件则直接加入
        else:
            result += list_files(item_path)  # 是目录则递归
    return result
2. 递归删除目录(不依赖 shutil)
复制代码
def remove_dir(path: str) -> None:
    """递归删除目录及所有内容(不使用shutil模块)"""
    # 先删除目录内所有子项
    for item in os.listdir(path):
        item_path = os.path.join(path, item)
        if os.path.isdir(item_path):
            remove_dir(item_path)  # 递归删除子目录
        else:
            os.remove(item_path)  # 删除文件
    os.rmdir(path)  # 最后删除空目录

三、文件描述符抽象类及实现

基于抽象基类定义文件读取接口,分别实现文本文件和字节文件的读取。

复制代码
from abc import ABC, abstractmethod

class InFileDescriptor(ABC):
    """文件读取抽象基类,定义基本接口"""
    def __init__(self, path=None):
        self._path = path  # 路径属性
        self._file = None  # 文件对象(子类初始化)

    @abstractmethod
    def read(self, n=1):
        """抽象方法:读取指定长度数据"""
        pass

    @abstractmethod
    def readall(self):
        """抽象方法:读取所有数据"""
        pass

    def chunks(self, chunk_size=8192):
        """生成器:分块读取数据(默认8KB)"""
        while True:
            data = self._file.read(chunk_size)
            if not data:  # 读取完毕
                break
            yield data

    @abstractmethod
    def close(self):
        """抽象方法:关闭文件流"""
        pass


class FileInput(InFileDescriptor):
    """文本文件读取类(字符模式)"""
    def __init__(self, path, *, encoding="UTF-8"):
        super().__init__(path)
        self._encoding = encoding  # 编码方式
        self._file = open(self._path, 'rt', encoding=encoding)  # 文本模式打开

    def read(self, n=1):
        """读取n个字符(默认1个)"""
        return self._file.read(n)

    def readline(self):
        """读取一行内容"""
        return self._file.readline()

    def readlines(self):
        """读取所有行,返回列表"""
        return self._file.readlines()

    def readall(self):
        """读取所有内容,返回字符串"""
        return self._file.read()

    def close(self):
        """关闭文件流"""
        self._file.close()


class FileInputStream(InFileDescriptor):
    """字节文件读取类(二进制模式)"""
    def __init__(self, path):
        super().__init__(path)
        self._file = open(self._path, 'rb')  # 二进制模式打开

    def read(self, n=1):
        """读取n个字节(默认1个)"""
        return self._file.read(n)

    def readall(self):
        """读取所有内容,返回字节串"""
        return self._file.read()

    def close(self):
        """关闭文件流"""
        self._file.close()

四、测试代码说明(原注释部分)

包含对FileUtils类的功能测试,主要流程:

  1. 创建测试目录和文件并写入内容
  2. 验证文件 / 目录存在性、大小、名称等属性
  3. 读取文件内容、筛选特定类型文件
  4. 测试文件和目录拷贝功能
  5. 测试删除功能及清理操作
相关推荐
天若有情6734 小时前
【python】Python爬虫入门教程:使用requests库
开发语言·爬虫·python·网络爬虫·request
IT北辰4 小时前
用Python+MySQL实战解锁企业财务数据分析
python·mysql·数据分析
Lucky高4 小时前
selenium(WEB自动化工具)
python
寒水馨4 小时前
Java 17 新特性解析与代码示例
java·开发语言·jdk17·新特性·java17
启山智软4 小时前
选用Java开发商城的优势
java·开发语言
秃然想通4 小时前
掌握Python三大语句:顺序、条件与循环
开发语言·python·numpy
##学无止境##5 小时前
Maven 从入门到精通:Java 项目构建与依赖管理全解析(上)
java·开发语言·maven
花火|5 小时前
算法训练营day37 动态规划⑤ 完全背包 518. 零钱兑换 II、 377. 组合总和 Ⅳ、70. 爬楼梯 (进阶)
算法·动态规划
Neil今天也要学习5 小时前
永磁同步电机无速度算法--脉振方波注入法
算法