🐍 前端开发 0 基础学 Python 入门指南:文件操作篇

144 阅读10分钟

🐍 前端开发 0 基础学 Python 入门指南:文件操作篇

从 JavaScript 的 fs 模块到 Python 的文件操作,让文件读写变得更简单!

📝 一、什么是文件操作?

文件操作是编程中的基础技能,用于读取、写入和处理文件数据。Python 提供了简洁而强大的文件操作 API,类似 Node.js 的 fs 模块,但更加简单易用。

1.1 基本概念

# 最简单的文件操作
f = open('demo.txt')      # 打开文件
content = f.read()        # 读取内容
f.close()                 # 关闭文件

核心特点:

  • 使用 open() 函数打开文件
  • 使用文件对象的方法进行读写
  • 必须调用 close() 关闭文件释放资源

🆚 二、Python vs JavaScript:文件操作对比

2.1 基本读取对比

特性Node.js (fs)Python
同步读取fs.readFileSync()open().read()
异步读取fs.readFile()使用异步库(如 aiofiles)
编码指定{encoding: 'utf-8'}encoding='utf-8'
错误处理try-catchtry-except
自动关闭无需关闭需要 close() 或使用 with
// JavaScript - 同步读取文件
const fs = require('fs');

try {
  const data = fs.readFileSync('demo.txt', 'utf-8');
  console.log(data);
} catch (err) {
  console.error('读取失败:', err);
}
# Python - 传统方式读取文件
try:
    f = open('demo.txt', encoding='utf-8')
    data = f.read()
    print(data)
except FileNotFoundError:
    print('读取失败: 文件不存在')
finally:
    f.close()  # 确保文件被关闭

2.2 异步读取对比

// JavaScript - 异步读取
const fs = require('fs').promises;

async function readFile() {
  try {
    const data = await fs.readFile('demo.txt', 'utf-8');
    console.log(data);
  } catch (err) {
    console.error('读取失败:', err);
  }
}
# Python - 使用 with 语句(推荐!)
try:
    with open('demo.txt', encoding='utf-8') as f:
        data = f.read()
        print(data)
    # 文件自动关闭,无需手动 close()
except FileNotFoundError:
    print('读取失败: 文件不存在')

💡 三、open() 函数详解

3.1 函数签名

open(file, mode='r', buffering=-1, encoding=None, errors=None,
     newline=None, closefd=True, opener=None)

3.2 常用参数

参数说明默认值
file文件路径(字符串或 Path 对象)必需
mode打开模式(读/写/追加等)'r'
encoding文件编码格式None
buffering缓冲策略-1
errors编码错误处理方式None

3.3 打开模式详解

# ====== 只读模式 ======
'r'    # 只读(默认)- 文件必须存在
'rb'   # 二进制只读 - 读取图片、视频等

# ====== 写入模式 ======
'w'    # 写入 - 文件存在则清空,不存在则创建
'wb'   # 二进制写入
'a'    # 追加 - 文件存在则在末尾追加,不存在则创建
'ab'   # 二进制追加

# ====== 读写模式 ======
'r+'   # 读写 - 文件指针在开头,文件必须存在
'w+'   # 读写 - 文件存在则清空,不存在则创建
'a+'   # 读写 - 文件指针在末尾,不存在则创建

# ====== 示例 ======
# 只读
with open('demo.txt', 'r', encoding='utf-8') as f:
    content = f.read()

# 写入(会覆盖原文件!)
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write('Hello, Python!')

# 追加
with open('log.txt', 'a', encoding='utf-8') as f:
    f.write('新日志\n')

# 二进制读取(图片等)
with open('image.png', 'rb') as f:
    image_data = f.read()

🔥 四、with 语句:最佳实践

4.1 为什么使用 with?

传统方式的问题:

# ❌ 不推荐:容易忘记关闭文件
f = open('demo.txt')
content = f.read()
f.close()  # 如果前面代码出错,这行不会执行!

# ❌ 更糟的情况
f = open('demo.txt')
content = f.read()
# 忘记 close(),导致资源泄漏

with 语句的优势:

# ✅ 推荐:自动关闭文件
with open('demo.txt', encoding='utf-8') as f:
    content = f.read()
    # 处理 content
# 离开 with 块后,文件自动关闭,即使发生异常也会关闭

4.2 with 语句的工作原理

# with 语句等价于:
f = open('demo.txt', encoding='utf-8')
try:
    content = f.read()
    # 处理内容
finally:
    f.close()  # 无论是否发生异常,都会执行

# 使用 with 更简洁:
with open('demo.txt', encoding='utf-8') as f:
    content = f.read()

4.3 同时打开多个文件

# 方式 1:嵌套 with
with open('input.txt', 'r', encoding='utf-8') as f_in:
    with open('output.txt', 'w', encoding='utf-8') as f_out:
        content = f_in.read()
        f_out.write(content.upper())

# 方式 2:一行 with(Python 3.1+,推荐!)
with open('input.txt', 'r', encoding='utf-8') as f_in, \
     open('output.txt', 'w', encoding='utf-8') as f_out:
    content = f_in.read()
    f_out.write(content.upper())

📖 五、文件读取方法

5.1 read() - 读取全部内容

# 一次性读取整个文件(适合小文件)
with open('demo.txt', encoding='utf-8') as f:
    content = f.read()  # 返回字符串
    print(content)

# 读取指定字节数(适合大文件)
with open('demo.txt', encoding='utf-8') as f:
    chunk = f.read(100)  # 只读取前 100 个字符
    print(chunk)

5.2 readline() - 逐行读取

# 读取单行
with open('demo.txt', encoding='utf-8') as f:
    line1 = f.readline()  # 读取第一行
    line2 = f.readline()  # 读取第二行
    print(line1, line2)

5.3 readlines() - 读取所有行到列表

# 读取所有行到列表
with open('demo.txt', encoding='utf-8') as f:
    lines = f.readlines()  # 返回列表,每行是一个元素
    print(lines)  # ['第一行\n', '第二行\n', '第三行\n']

# 常见用法:处理每一行
with open('demo.txt', encoding='utf-8') as f:
    lines = f.readlines()
    for line in lines:
        print(line.strip())  # strip() 去除换行符

5.4 遍历文件对象(最推荐!)

# ✅ 最佳实践:直接遍历文件对象
# 优点:内存友好,适合大文件
with open('demo.txt', encoding='utf-8') as f:
    for line in f:
        print(line.strip())

# 等价于 readlines(),但不会一次性加载到内存

5.5 读取方法对比

方法返回类型适用场景内存占用
read()字符串小文件
read(size)字符串大文件分块
readline()字符串逐行处理
readlines()列表小文件
for line迭代器推荐!最低

✍️ 六、文件写入方法

6.1 write() - 写入字符串

# 写入单个字符串
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write('Hello, Python!\n')
    f.write('第二行内容\n')
    # 返回写入的字符数

# ⚠️ 注意:write() 不会自动添加换行符
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write('行1')
    f.write('行2')  # 结果:行1行2(没有换行!)

6.2 writelines() - 写入列表

# 写入字符串列表
lines = ['第一行\n', '第二行\n', '第三行\n']
with open('output.txt', 'w', encoding='utf-8') as f:
    f.writelines(lines)

# ⚠️ 注意:writelines() 也不会自动添加换行符
lines = ['行1', '行2', '行3']
with open('output.txt', 'w', encoding='utf-8') as f:
    f.writelines(lines)  # 结果:行1行2行3(没有换行!)
    
# ✅ 正确做法:手动添加换行符
with open('output.txt', 'w', encoding='utf-8') as f:
    f.writelines([line + '\n' for line in lines])

6.3 print() 直接写入文件

# ✨ 使用 print() 写入文件(自动换行!)
with open('output.txt', 'w', encoding='utf-8') as f:
    print('第一行', file=f)
    print('第二行', file=f)
    print('第三行', file=f)
    # 自动添加换行符,非常方便!

🗂️ 七、os 模块:文件和目录操作

7.1 导入 os 模块

import os

# 获取当前工作目录
current_dir = os.getcwd()
print(f'当前目录:{current_dir}')

# 切换工作目录
os.chdir('/Users/wang/Documents')
print(f'切换后:{os.getcwd()}')

7.2 路径操作

import os

# 拼接路径(跨平台兼容)
path = os.path.join('folder', 'subfolder', 'file.txt')
print(path)  # macOS/Linux: folder/subfolder/file.txt
             # Windows: folder\subfolder\file.txt

# 获取绝对路径
abs_path = os.path.abspath('demo.txt')
print(abs_path)  # /Users/wang/Documents/python/demo.txt

# 判断路径是否存在
if os.path.exists('demo.txt'):
    print('文件存在')

# 判断是否为文件/目录
print(os.path.isfile('demo.txt'))   # True
print(os.path.isdir('demo'))        # True

# 获取文件大小(字节)
size = os.path.getsize('demo.txt')
print(f'文件大小:{size} 字节')

# 分割路径
dir_name = os.path.dirname('/Users/wang/demo.txt')   # /Users/wang
file_name = os.path.basename('/Users/wang/demo.txt') # demo.txt
name, ext = os.path.splitext('demo.txt')             # ('demo', '.txt')

7.3 目录操作

import os

# 创建目录
os.mkdir('new_folder')           # 创建单层目录
os.makedirs('a/b/c')             # 创建多层目录

# 删除目录
os.rmdir('new_folder')           # 删除空目录
os.removedirs('a/b/c')           # 删除多层空目录

# 列出目录内容
files = os.listdir('.')          # 当前目录所有文件和文件夹
print(files)

# 遍历目录树
for root, dirs, files in os.walk('.'):
    print(f'目录:{root}')
    print(f'子目录:{dirs}')
    print(f'文件:{files}')

7.4 文件操作

import os

# 重命名文件
os.rename('old.txt', 'new.txt')

# 删除文件
os.remove('file.txt')

# 执行系统命令
os.system('ls -l')  # macOS/Linux
os.system('dir')    # Windows

7.5 环境变量

import os

# 获取环境变量
home = os.environ.get('HOME')
path = os.environ.get('PATH')

# 设置环境变量(仅当前进程有效)
os.environ['MY_VAR'] = 'my_value'

🔄 八、实战:循环文件合并

8.1 合并两个文件

# 方式 1:分别读取再合并
with open('demo.txt', encoding='utf-8') as file1:
    file1_data = file1.read()

with open('demo2.txt', encoding='utf-8') as file2:
    file2_data = file2.read()

with open('merged.txt', 'w', encoding='utf-8') as merged_file:
    merged_file.write(file1_data)
    merged_file.write('\n')  # 添加换行符分隔
    merged_file.write(file2_data)

print('✅ 文件合并完成!')
# 方式 2:使用一行 with(更优雅)
with open('demo.txt', encoding='utf-8') as f1, \
     open('demo2.txt', encoding='utf-8') as f2, \
     open('merged.txt', 'w', encoding='utf-8') as out:
    out.write(f1.read())
    out.write('\n')
    out.write(f2.read())

8.2 合并多个文件(循环)

# ✨ 批量合并文件
filenames = ['file1.txt', 'file2.txt', 'file3.txt']

with open('merged.txt', 'w', encoding='utf-8') as outfile:
    for fname in filenames:
        print(f'正在合并:{fname}')
        with open(fname, 'r', encoding='utf-8') as infile:
            outfile.write(infile.read())
            outfile.write('\n')  # 文件之间添加换行
    
print('✅ 所有文件合并完成!')

8.3 高级:带分隔符的合并

import os

filenames = ['file1.txt', 'file2.txt', 'file3.txt']

with open('merged.txt', 'w', encoding='utf-8') as outfile:
    for i, fname in enumerate(filenames, 1):
        if not os.path.exists(fname):
            print(f'⚠️  文件不存在:{fname}')
            continue
            
        # 写入分隔符
        outfile.write(f'\n{"="*50}\n')
        outfile.write(f'文件 {i}: {fname}\n')
        outfile.write(f'{"="*50}\n\n')
        
        # 写入文件内容
        with open(fname, 'r', encoding='utf-8') as infile:
            outfile.write(infile.read())
        
        print(f'✅ 已合并:{fname}')

print('\n🎉 所有文件合并完成!')

8.4 自动查找并合并

import os

# 自动查找当前目录下所有 .txt 文件并合并
txt_files = [f for f in os.listdir('.') if f.endswith('.txt')]

print(f'找到 {len(txt_files)} 个 txt 文件:')
for f in txt_files:
    print(f'  - {f}')

with open('all_merged.txt', 'w', encoding='utf-8') as outfile:
    for fname in sorted(txt_files):  # 按文件名排序
        print(f'合并中:{fname}')
        outfile.write(f'\n=== {fname} ===\n\n')
        
        with open(fname, 'r', encoding='utf-8') as infile:
            outfile.write(infile.read())
            outfile.write('\n')

print('✅ 合并完成!')

🎯 九、文件编码处理

9.1 常见编码问题

# ❌ 错误:不指定编码(可能乱码)
with open('demo.txt') as f:
    content = f.read()

# ✅ 正确:指定编码
with open('demo.txt', encoding='utf-8') as f:
    content = f.read()

9.2 常见编码格式

编码说明使用场景
utf-8万国码(推荐!)现代文件默认
gbk中文编码Windows 中文系统
gb2312简体中文老版本中文文件
ascii英文编码纯英文文件
latin-1西欧编码部分欧洲语言文件
# 处理不同编码的文件
encodings = ['utf-8', 'gbk', 'gb2312', 'latin-1']

for encoding in encodings:
    try:
        with open('demo.txt', encoding=encoding) as f:
            content = f.read()
            print(f'✅ 使用 {encoding} 编码读取成功')
            break
    except UnicodeDecodeError:
        print(f'❌ {encoding} 编码失败')

9.3 编码转换

# 将 GBK 文件转换为 UTF-8
with open('gbk_file.txt', 'r', encoding='gbk') as f:
    content = f.read()

with open('utf8_file.txt', 'w', encoding='utf-8') as f:
    f.write(content)

print('✅ 编码转换完成:GBK → UTF-8')

🛡️ 十、异常处理

10.1 常见文件异常

import os

filename = 'demo.txt'

try:
    with open(filename, 'r', encoding='utf-8') as f:
        content = f.read()
        print(content)
        
except FileNotFoundError:
    print(f'❌ 文件不存在:{filename}')
    
except PermissionError:
    print(f'❌ 没有权限访问:{filename}')
    
except UnicodeDecodeError:
    print(f'❌ 编码错误,请尝试其他编码格式')
    
except IOError as e:
    print(f'❌ IO 错误:{e}')
    
except Exception as e:
    print(f'❌ 未知错误:{e}')

10.2 安全的文件操作

def safe_read_file(filename, encoding='utf-8'):
    """安全地读取文件"""
    # 检查文件是否存在
    if not os.path.exists(filename):
        print(f'❌ 文件不存在:{filename}')
        return None
    
    # 检查是否为文件
    if not os.path.isfile(filename):
        print(f'❌ 不是文件:{filename}')
        return None
    
    # 检查文件大小(避免读取超大文件)
    size = os.path.getsize(filename)
    if size > 10 * 1024 * 1024:  # 10MB
        print(f'⚠️  文件太大:{size / 1024 / 1024:.2f} MB')
        return None
    
    # 读取文件
    try:
        with open(filename, 'r', encoding=encoding) as f:
            return f.read()
    except Exception as e:
        print(f'❌ 读取失败:{e}')
        return None

# 使用
content = safe_read_file('demo.txt')
if content:
    print(content)

📚 十一、总结

核心要点

  1. 使用 with 语句:自动管理文件关闭,避免资源泄漏
  2. 指定编码格式:优先使用 encoding='utf-8'
  3. 选择合适的读取方法
    • 小文件:read()
    • 大文件:for line in file(推荐)
    • 需要列表:readlines()
  4. os 模块:处理路径、目录、文件信息
  5. 异常处理:使用 try-except 捕获文件操作异常

Python vs JavaScript 文件操作

特性Node.jsPython
打开文件fs.readFileSync()open()
自动关闭不需要需要 withclose()
同步读取readFileSync()read()
异步读取readFile() / promisesaiofiles(需要安装)
路径操作path 模块os.path 模块
目录操作fs.mkdir()os.mkdir()
编码指定{encoding: 'utf-8'}encoding='utf-8'

最佳实践

  • 永远使用 with 语句打开文件
  • 明确指定 encoding参数
  • 使用 os.path.join() 拼接路径(跨平台兼容)
  • 大文件使用迭代器for line in file
  • 添加异常处理,提高程序健壮性
  • ❌ 避免忘记关闭文件
  • ❌ 避免一次性读取超大文件到内存
  • ❌ 避免硬编码路径分隔符(用 os.path.join()

常用代码模板

# 📖 读取文件模板
with open('file.txt', 'r', encoding='utf-8') as f:
    content = f.read()

# ✍️ 写入文件模板
with open('file.txt', 'w', encoding='utf-8') as f:
    f.write('content')

# 🔄 逐行处理模板(推荐)
with open('file.txt', encoding='utf-8') as f:
    for line in f:
        process(line.strip())

# 🗂️ 路径操作模板
import os
path = os.path.join('folder', 'file.txt')
if os.path.exists(path):
    with open(path, encoding='utf-8') as f:
        content = f.read()

# 🔗 文件合并模板
files = ['f1.txt', 'f2.txt', 'f3.txt']
with open('merged.txt', 'w', encoding='utf-8') as out:
    for fname in files:
        with open(fname, encoding='utf-8') as f:
            out.write(f.read())
            out.write('\n')

本文适合前端开发者快速掌握 Python 文件操作,通过对比 Node.js 的 fs 模块来理解 Python 的文件处理机制。记住:永远使用 with 语句,明确指定编码 🚀