Python
基础语法
01概念
02安装
03变量
04字符串
05数
06常量与注释
07列表
08元组
09if语句
10字典
11集合
12复合数据类型对比
13推导式
14用户输入
15while循环
16函数
17类
18面向对象编程
19文件操作
20异常处理
21日期和时间
22魔术方法
23内置函数
24线程
25并发&并行
26正则表达式
27迭代器
28装饰器
29生成器
30上下文管理器
31函数式编程
32闭包
33解包
34工具库
35连接关系型数据库
36虚拟环境
37异步编程
网络爬虫
01urllib库[了解]
02requests库
03数据交换格式
04解析库
05lxml
06Beautiful Soup
07Xpath语法
08动态网页的处理
-
+
首页
19文件操作
在 Python 中,**文件操作**是指对存储在磁盘上的文件进行创建、读取、写入、修改、删除等操作的过程。它是程序与外部数据交互的核心方式(如读取配置文件、保存用户数据、处理日志等)。 ## 概念 **文件的本质**:存储在磁盘上的二进制或文本数据集合,通过 “路径” 唯一标识(如/home/data.txt或C:\docs\note.txt)。 **操作类型**:创建、读取、写入、修改、删除、移动、复制等。 **核心流程**:打开文件→操作文件→关闭文件(释放系统资源,如文件句柄)。 ## 文件路径 路径(path)指的是文件或者文件夹在系统中的准确位置;提供特定功能的模块通常称为库(library)。 文件路径是定位文件的 “地址”,需注意跨平台差异: - **Windows**:使用反斜杠\(如C:\Users\file.txt),但 Python 中可写为C:/Users/file.txt(正斜杠兼容)。 - **Linux/macOS**:使用正斜杠/(如/home/user/file.txt)。 路径分类: - **绝对路径**:从根目录开始的完整路径(如/usr/local/bin)。 - **相对路径**:相对于当前程序运行目录的路径(如./data/file.txt,./表示当前目录,../表示上级目录)。 ## 传统文件操作 传统文件操作:open()函数与文件对象。 open()是 Python 内置函数,用于建立程序与文件的连接,返回 “文件对象”(文件句柄),是最基础的文件操作工具。 ### **语法** ```python file_object = open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) ``` 其中file表示文件路径(字符串或者Path对象)、mode表示打开模块(确定操作类型和文件类型)、encoding表示文件文本的编码格式(二进制模式无需指定)。 python 官方的详细文档:https://docs.python.org/zh-cn/3/library/functions.html#open 常见的mode模块有如下几种: | 模式 | 含义(文本模式) | | | | ---- | ------------------------------------------ | ---- | ---- | | r | 只读(默认),文件不存在则报错 | | | | w | 只写,文件不存在则创建,存在则清空内容 | | | | a | 追加,文件不存在则创建,存在则内容写在末尾 | | | | + | 打开用于更新(读取与写入) | | | | b | 二进制模式 | | | | t | 文本模式(默认) | | | 注意: - 文本模式(无b):操作的是字符串(str),会自动进行编码 / 解码(依赖encoding参数)。 - 二进制模式(带b):操作的是字节流(bytes),适用于非文本文件(图片、视频、压缩包等),无需指定encoding。 ### **文件对象的操作** 文件对象(file_object)提供了一系列方法用于操作文件,核心方法如下: | 方法 | 功能描述 | | ---------------------- | ------------------------------------------------------------ | | read(size=-1) | 读取文件内容:size为字节数(文本模式按字符),默认-1表示读取全部内容。 | | readline(size=-1) | 读取一行内容(包括换行符\n),size限制最大字符 / 字节数。 | | readlines(hint=-1) | 读取所有行,返回列表(每行作为元素),hint限制总字符 / 字节数。 | | write(s) | 写入内容:文本模式传入字符串(str),二进制模式传入字节流(bytes)。 | | writelines(lines) | 写入多行:传入可迭代对象(如列表),需自行添加换行符\n。 | | seek(offset, whence=0) | 移动文件指针(定位到指定位置):offset为偏移量,whence为基准(0:文件开头,1:当前位置,2:文件末尾)。 | | tell() | 返回当前文件指针的位置(字节数)。 | | close() | 关闭文件,释放资源(必须执行,否则可能导致数据丢失或资源泄漏)。 | | flush() | 强制将缓冲区内容写入磁盘(无需关闭文件)。 | ### 示例 **读取文本文件** ```python # 打开文件(文本模式,utf-8编码) file = open("test.txt", "r", encoding="utf-8") # 方法1:读取全部内容 content = file.read() print("全部内容:", content) # 移动指针到开头(因为read()后指针在末尾) file.seek(0) # 方法2:逐行读取(适合大文件,避免内存占用过高) print("\n逐行读取:") line = file.readline() while line: print(line.strip()) # strip()去除换行符 line = file.readline() # 关闭文件 file.close() ``` **写入文本文件** ```python # 打开文件(只写模式,不存在则创建) file = open("output.txt", "w", encoding="utf-8") # 写入单条内容 file.write("Hello, Python!\n") # 手动添加换行符 # 写入多条内容 lines = ["第一行\n", "第二行\n", "第三行\n"] file.writelines(lines) # 关闭文件(重要:确保内容写入磁盘) file.close() ``` **追加内容到文件** ```python # 打开文件(追加模式) with open("output.txt", "a", encoding="utf-8") as file: file.write("这是追加的内容\n") # 内容会添加到文件末尾 ``` **二进制文件读写** ```python # 读取图片(二进制模式) with open("image.jpg", "rb") as f: img_data = f.read() # 获得字节流 # 写入图片(复制文件) with open("copy_image.jpg", "wb") as f: f.write(img_data) # 将字节流写入新文件 ``` ### 上下文管理 手动调用close()可能因遗漏(如程序异常)导致文件未关闭,引发资源泄漏或数据丢失。 Python 的**上下文管理器**(with语句)可自动管理文件生命周期:进入with块时打开文件,离开块时自动关闭文件 ,无需手动调用close()。 语法: ```python with open(文件路径, 模式, 编码) as 文件对象: # 文件操作代码(缩进块内) pass # 离开缩进块后,文件自动关闭 ``` 例如: ```python # 用with语句读取文件(推荐方式) with open("test.txt", "r", encoding="utf-8") as file: content = file.read() print(content) # 离开with块后,file自动关闭,无需手动操作 ``` ### 路径处理 处理文件路径时,需考虑不同操作系统的路径分隔符(Windows 用\,Linux/macOS 用/)。Python 的os.path模块提供了跨平台的路径处理工具: ```python import os # 获取当前工作目录 current_dir = os.getcwd() print("当前目录:", current_dir) # 拼接路径(自动适配系统分隔符) file_path = os.path.join(current_dir, "data", "test.txt") print("拼接后的路径:", file_path) # 检查文件是否存在 if os.path.exists(file_path): print("文件存在") else: print("文件不存在") ``` ## 现代文件操作 在 Python 中,除了传统的open()函数,还可以通过 **pathlib模块**的Path类进行文件操作。pathlib是 Python 3.4 + 引入的内置库,它提供了**面向对象的文件系统路径操作接口 **,相比os.path模块的字符串操作方式,更直观、简洁,且支持链式调用,尤其适合处理路径拼接、文件读写、目录遍历等场景。 ### 优势 **面向对象设计**:将文件路径视为 “对象”,通过方法直接操作(如path.read_text()),而非字符串拼接。 **跨平台兼容**:自动处理不同操作系统的路径分隔符(Windows 用\,Linux/macOS 用/)。 **链式操作**:支持连续调用方法(如path.parent.joinpath("new_file.txt")),代码更简洁。 **集成文件操作**:内置读写方法(如read_text()、write_text()),无需手动调用open()和close()。 ### 基本使用 **导入Path类** ```python from pathlib import Path ``` **创建Path对象** ```python # 绝对路径:从根目录开始 abs_path = Path("/home/user/data/test.txt") # Linux/macOS abs_path = Path("C:/Users/user/data/test.txt") # Windows # 相对路径:相对于当前工作目录 rel_path = Path("data/test.txt") # 当前目录下的data文件夹 rel_path = Path("./data/test.txt") # 等价于上面(./表示当前目录) rel_path = Path("../data/test.txt") # 上级目录下的data文件夹 # 当前工作目录 current_dir = Path.cwd() # 等价于os.getcwd() # 用户主目录 home_dir = Path.home() # 等价于os.path.expanduser("~") ``` **路径属性与拼接** Path对象提供了丰富的属性和方法处理路径: | 操作 | 代码示例 | 说明 | | -------------------- | -------------------------------- | ---------------------------- | | 获取文件名 | path.name | 包含扩展名(如test.txt) | | 获取文件名(无扩展) | path.stem | 不含扩展名(如test) | | 获取扩展名 | path.suffix | 如.txt,无扩展名则为空字符串 | | 获取父目录 | path.parent | 返回父目录的Path对象 | | 拼接路径 | path.joinpath("sub", "file.txt") | 拼接子路径,返回新Path对象 | | 检查是否绝对路径 | path.is_absolute() | 返回布尔值 | ```python path = Path("data/reports/2023_sales.csv") print(path.name) # 输出:2023_sales.csv print(path.stem) # 输出:2023_sales print(path.suffix) # 输出:.csv print(path.parent) # 输出:data/reports print(path.parent.parent) # 输出:data(父目录的父目录) # 拼接新路径 new_path = path.parent.joinpath("2024_sales.csv") print(new_path) # 输出:data/reports/2024_sales.csv ``` ### 文件读写 Path类内置了简洁的文件读写方法,无需手动管理open()和close(),底层自动处理资源释放。 **文本文件的读写** - read_text(encoding=None):读取文本文件内容,返回字符串。 - write_text(data, encoding=None):写入字符串到文本文件,覆盖原有内容。 - append_text(data, encoding=None):追加字符串到文本文件末尾(Python 3.10 + 支持)。 ```python path = Path("notes.txt") # 写入文本(覆盖模式) path.write_text("Hello, Pathlib!\n这是用Path类写入的文本。", encoding="utf-8") # 读取文本 content = path.read_text(encoding="utf-8") print(content) # 输出: # Hello, Pathlib! # 这是用Path类写入的文本。 # 追加文本(Python 3.10+) path.append_text("\n这是追加的内容。", encoding="utf-8") ``` **二进制文件读写** - read_bytes():读取二进制文件内容,返回字节流(bytes)。 - write_bytes(data):写入字节流到二进制文件,覆盖原有内容。 ```python src = Path("image.jpg") dst = Path("image_copy.jpg") # 读取二进制数据并写入新文件 dst.write_bytes(src.read_bytes()) ``` **高级读写(自定义模式)** 若需更灵活的操作(如读写模式r+、按行读取),可通过Path.open()方法获取文件对象,用法类似内置open(): ```python path = Path("data.txt") # 读写模式打开(r+) with path.open("r+", encoding="utf-8") as f: content = f.read() # 读取内容 f.seek(0) # 移动指针到开头 f.write("新内容:" + content) # 覆盖写入 ``` ### 目录操作 Path类也提供了目录相关的方法(创建、删除、遍历等): | 操作 | 代码示例 | 说明 | | -------------------- | ----------------------------- | ------------------------------------------- | | 检查路径是否存在 | path.exists() | 返回布尔值(文件或目录存在) | | 检查是否为文件 | path.is_file() | 返回布尔值 | | 检查是否为目录 | path.is_dir() | 返回布尔值 | | 创建目录(单级) | path.mkdir(exist_ok=False) | exist_ok=True表示目录存在时不报错 | | 创建目录(多级) | path.mkdir(parents=True) | 递归创建父目录(如a/b/c) | | 删除文件 | path.unlink(missing_ok=False) | missing_ok=True表示文件不存在时不报错 | | 删除目录 | path.rmdir() | 只能删除空目录 | | 遍历目录下的文件 | path.iterdir() | 返回目录下所有文件 / 子目录的Path对象迭代器 | | 查找文件(匹配模式) | path.glob("*.txt") | 返回匹配模式的Path对象(如所有.txt文件) | 例如:创建目录并遍历文件 ```python # 创建多级目录 dir_path = Path("data/reports/2023") dir_path.mkdir(parents=True, exist_ok=True) # parents=True允许创建多级目录 # 在目录中创建文件 file1 = dir_path.joinpath("Jan.csv") file1.write_text("1月数据") file2 = dir_path.joinpath("Feb.csv") file2.write_text("2月数据") # 遍历目录下的文件 print("目录下的文件:") for item in dir_path.iterdir(): if item.is_file(): # 只打印文件(排除子目录) print(item.name) # 输出:Jan.csv、Feb.csv # 查找所有.csv文件 csv_files = dir_path.glob("*.csv") print("\n所有CSV文件:", [f.name for f in csv_files]) # 输出:['Jan.csv', 'Feb.csv'] ``` ## 两种方式对比 pathlib.Path 与传统的 open() 函数在文件操作中各有侧重,核心区别体现在**设计理念**和**功能范围**上。 open() 是专门用于 “打开文件并获取文件对象” 的函数,而 Path 是面向对象的路径管理工具,整合了路径处理和文件读写功能。 | 特性 | open() 函数 | pathlib.Path 类 | | ------------ | --------------------------------------------- | ------------------------------------------------------------ | | **核心定位** | 仅负责 “打开文件”,返回文件对象(用于读写)。 | 以 “路径对象” 为核心,整合**路径处理**(拼接、判断等)和**文件读写**功能。 | | **设计理念** | 函数式编程(通过函数操作文件)。 | 面向对象编程(通过对象的方法操作路径和文件)。 | | **依赖** | 单独使用时,路径处理需配合 os.path 模块。 | 内置路径处理能力,无需依赖其他模块。 | **场景对比** | 场景 | 推荐工具 | 原因分析 | | ------------------------------- | ------------ | ------------------------------------------------------ | | 简单文本 / 二进制文件读写 | pathlib.Path | 代码更简洁(一行完成读写),无需处理 with 和路径拼接。 | | 路径拼接、判断文件 / 目录存在性 | pathlib.Path | 面向对象的路径操作更直观,跨平台兼容性更好。 | | 大文件读写(需逐行 / 分块处理) | open() 函数 | 可通过 readline() 逐行读取,避免一次性加载占用内存。 | | 随机读写(移动文件指针) | open() 函数 | 直接操作文件对象的 seek()/tell() 更灵活。 | | 复杂文件模式(如 r+ 读写) | open() 函数 | 对模式的控制更直接,适合需要同时读写的场景。 | | 批量文件处理(遍历目录、查找) | pathlib.Path | 内置 iterdir()/glob() 等方法,简化目录遍历和文件筛选。 | ## 文件存储 在 Python 爬虫中,获取数据后通常需要**持久化存储**(保存到文件或数据库),以便后续分析、展示或二次处理。 文件存储是最基础的持久化方式,适用于中小规模数据,常见格式包括文本文件、CSV、JSON、Excel 以及二进制文件(如图片、视频)等。 ### 文本文件存储(TXT格式) 文本文件(.txt)是最通用、最简单的存储格式,适用于保存非结构化或半结构化数据(如网页 HTML 源码、日志、纯文本内容等)。其优点是兼容性强(几乎所有系统都能打开),缺点是不适合存储复杂结构化数据(如表格)。 Python 通过内置的 `open()` 函数操作文本文件,语法: ```python with open(file_path, mode, encoding) as file: # 读写操作 ``` **`file_path`**:文件路径(绝对路径或相对路径)。 **`mode`**:打开模式(常用模式如下): | 模式 | 含义 | | ------ | -------------------------------------------- | | `'r'` | 只读(默认),文件不存在则报错 | | `'w'` | 只写,覆盖原有内容(文件不存在则创建) | | `'a'` | 追加,在文件末尾添加内容(文件不存在则创建) | | `'r+'` | 读写 | **`encoding`**:编码格式(推荐 `'utf-8'`,避免中文乱码)。 ```python import requests # 爬取百度首页HTML url = "https://www.baidu.com" response = requests.get(url) response.encoding = "utf-8" # 确保编码正确 html_content = response.text # 保存到txt文件 file_path = "baidu_homepage.txt" with open(file_path, "w", encoding="utf-8") as f: f.write(html_content) # 写入字符串 print(f"HTML内容已保存到 {file_path}") ``` ### CSV 文件存储 CSV(Comma-Separated Values,逗号分隔值)是一种轻量级表格数据格式,适用于存储结构化数据(如用户信息、商品列表、统计数据等)。 其优点是体积小、解析快,可被 Excel、Google Sheets 等工具直接打开,是爬虫存储表格数据的首选格式之一。 Python 内置 `csv` 模块,支持 CSV 文件的读写,核心类包括: - **`csv.writer`**:通过列表写入数据(适合简单场景)。 - **`csv.DictWriter`**:通过字典写入数据(键对应表头,值对应内容,更直观)。 ```python import csv import os # 模拟爬虫获取的结构化数据(列表嵌套列表) data = [ ["姓名", "年龄", "城市"], # 表头 ["张三", 25, "北京"], ["李四", 30, "上海"], ["王五", 28, "广州"] ] # 保存路径 file_path = os.path.join("data", "users.csv") os.makedirs(os.path.dirname(file_path), exist_ok=True) # 写入CSV with open(file_path, "w", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) # 创建writer对象 writer.writerows(data) # 批量写入多行(writerow() 写入单行) print(f"CSV数据已保存到 {file_path}") ``` - **`newline=""`**:避免 Windows 系统中写入时自动添加空行。 - **`encoding="utf-8-sig"`**:解决 Excel 打开 CSV 时中文乱码问题(`utf-8-sig` 带 BOM 头,Excel 可识别)。 - 分隔符:默认用逗号分隔,若数据含逗号,可通过 `delimiter="|"` 指定其他分隔符(如竖线)。 ### JSON 文件存储 JSON(JavaScript Object Notation)是一种轻量级结构化数据格式,适合存储层次化数据(如 API 返回的嵌套结构、复杂对象)。其优点是易于人类阅读,可被几乎所有编程语言解析,常用于数据交换或配置文件。 Python 内置 `json` 模块,支持 JSON 与 Python 数据类型的转换,核心方法: - **`json.dump(obj, fp)`**:将 Python 对象(字典 / 列表)写入文件(JSON 格式)。 - **`json.dumps(obj)`**:将 Python 对象转换为 JSON 字符串。 - **`json.load(fp)`**:从文件读取 JSON 并转换为 Python 对象。 ```python import json import os # 模拟单条爬虫数据(字典) data = { "name": "Python爬虫实战", "author": "张三", "publish_date": "2023-01-01", "tags": ["爬虫", "Python", "数据解析"], "price": 59.9 } file_path = os.path.join("data", "book.json") os.makedirs(os.path.dirname(file_path), exist_ok=True) # 写入JSON文件 with open(file_path, "w", encoding="utf-8") as f: # ensure_ascii=False:保留中文(否则会转为Unicode编码) # indent=2:格式化输出(缩进2空格,增强可读性) json.dump(data, f, ensure_ascii=False, indent=2) print(f"JSON数据已保存到 {file_path}") ``` 值得注意的是: - **数据类型限制**:JSON 仅支持字符串、数字、布尔、null、数组、对象(字典),不支持 Python 的元组、集合、日期等类型,需先转换(如元组转列表)。 - **大文件问题**:JSON 不适合 GB 级大文件(解析时需全部加载到内存),此类场景建议用数据库或行分隔 JSON(JSON Lines)。 ### Excel 文件存储 Excel(.xlsx/.xls)是办公场景中常用的表格格式,支持复杂样式、公式、图表等,适合需要交付给非技术人员的数据。 Python 中常用 `openpyxl`(处理.xlsx)和 `xlwt`(处理.xls)库操作 Excel。 - **`openpyxl`**:支持.xlsx 格式(Excel 2007+),功能全面(读写、样式设置),推荐使用。 安装:`pip install openpyxl` - **`xlwt`**:仅支持.xls 格式(旧版 Excel),不支持.xlsx,适合兼容性需求。 安装:`pip install xlwt` ```python from openpyxl import Workbook from openpyxl.styles import Font, Alignment import os # 1. 创建工作簿(Workbook)和工作表(Worksheet) wb = Workbook() ws = wb.active # 获取默认工作表 ws.title = "用户数据" # 设置工作表名称 # 2. 写入表头(第一行) headers = ["ID", "姓名", "年龄", "城市"] for col, header in enumerate(headers, 1): # 列从1开始(Excel列号从A=1开始) cell = ws.cell(row=1, column=col) cell.value = header # 设置表头样式(加粗、居中) cell.font = Font(bold=True) cell.alignment = Alignment(horizontal="center") # 3. 写入数据(从第二行开始) data = [ (1, "张三", 25, "北京"), (2, "李四", 30, "上海"), (3, "王五", 28, "广州") ] for row, (id, name, age, city) in enumerate(data, 2): # 行从2开始 ws.cell(row=row, column=1, value=id) ws.cell(row=row, column=2, value=name) ws.cell(row=row, column=3, value=age) ws.cell(row=row, column=4, value=city) # 4. 调整列宽(自适应内容) for col in ws.columns: max_length = 0 column = col[0].column_letter # 获取列号(如A、B) for cell in col: try: if len(str(cell.value)) > max_length: max_length = len(str(cell.value)) except: pass adjusted_width = max_length + 2 # 加2避免内容溢出 ws.column_dimensions[column].width = adjusted_width # 5. 保存文件 file_path = os.path.join("data", "users.xlsx") os.makedirs(os.path.dirname(file_path), exist_ok=True) wb.save(file_path) print(f"Excel数据已保存到 {file_path}") ``` 值得注意的是: - **格式兼容性**:`.xlsx` 比 `.xls` 支持更大数据量(.xls 单表最多 65536 行),优先使用 `.xlsx`。 - **性能问题**:Excel 文件体积较大,写入 10 万行以上数据时速度较慢,建议用 CSV 或数据库替代。 ### 二进制文件存储(图片、视频等) 爬虫常需下载图片、视频、音频等二进制文件,这类文件无法直接用文本方式读写,需以二进制模式(`'rb'`/`'wb'`)操作。 核心思路: - 用 `requests.get()` 获取二进制内容(`response.content`,字节流)。 - 用 `open(..., 'wb')` 写入文件。 例如:下载单张图片 ```python import requests import os # 图片URL(示例:一张Python相关图片) img_url = "https://picsum.photos/id/0/800/600" # picsum是免费图片占位服务 img_name = "python_image.jpg" # 保存的文件名 # 创建保存目录 save_dir = "images" os.makedirs(save_dir, exist_ok=True) file_path = os.path.join(save_dir, img_name) # 发送请求并下载 try: # 流式获取(适合大文件) with requests.get(img_url, stream=True, timeout=10) as response: response.raise_for_status() # 检查请求是否成功 # 写入二进制文件 with open(file_path, "wb") as f: for chunk in response.iter_content(chunk_size=8192): # 分块写入(8KB/块) f.write(chunk) print(f"图片已保存到 {file_path}") except Exception as e: print(f"下载失败:{e}") ``` ## 总结 **优先使用with语句**:无论是open()还是Path.open(),with能自动关闭文件,避免资源泄漏。 ```python with Path("file.txt").open("r") as f: # Path与with结合 for line in f: process(line) ``` **明确编码**:文本文件操作指定encoding="utf-8"(或其他编码),避免中文乱码。 **处理大文件**:分块读取(read(1024))或逐行迭代,不一次性加载到内存。 **路径用Path对象**:替代字符串拼接,减少跨平台错误(如Path("a") / "b"等价于a/b)。 **避免from 模块 import \***:导入pathlib时用from pathlib import Path,保持代码清晰。 **open()函数**适合底层、复杂的读写控制(如大文件、随机读写); **pathlib.Path**适合路径处理和简单读写,代码更简洁、可读性更强。 值得注意的是:在读取文本文件时,python将其中的所有文本都解释为字符串类型,如果要读取的是数,并且要将其作为数值使用,就必须使用init()函数将其转换为整数或者使用float()函数将其转换为浮点数。
毛林
2025年9月7日 11:45
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码