Python输入输出操作与文件处理完全指南

📅 2026/7/19 3:21:34 👁️ 阅读次数 📝 编程学习
Python输入输出操作与文件处理完全指南

1. Python输入输出基础概念

在Python编程中,输入输出(I/O)是与用户交互和数据处理的基础功能。Python提供了多种简单而强大的方式来处理输入输出操作,这些操作主要分为三类:标准输入输出、文件操作和数据序列化。

1.1 标准输入输出

标准输入输出是最基础的交互方式,主要通过控制台进行。Python使用内置函数input()获取用户输入,使用print()函数输出内容到控制台。

# 获取用户输入 user_input = input("请输入您的名字:") print("您好,", user_input)

input()函数总是返回字符串类型,如果需要其他类型的数据,必须进行类型转换:

age = int(input("请输入您的年龄:")) print("明年您将", age + 1, "岁")

1.2 文件操作基础

文件操作是更高级的I/O方式,Python通过open()函数创建文件对象,支持多种模式(读、写、追加等)。文件操作的基本流程是:打开文件→进行操作→关闭文件。

# 基本文件写入示例 with open('example.txt', 'w') as f: f.write("这是写入文件的内容")

1.3 数据序列化

对于复杂数据结构,Python提供了pickle模块进行序列化和反序列化操作,可以将Python对象转换为字节流保存到文件,或从文件还原为对象。

import pickle data = {'name': '张三', 'age': 25, 'skills': ['Python', 'Java']} # 序列化到文件 with open('data.pkl', 'wb') as f: pickle.dump(data, f) # 从文件反序列化 with open('data.pkl', 'rb') as f: loaded_data = pickle.load(f)

2. 格式化输出详解

Python提供了多种方式来格式化输出内容,使输出更加美观和易读。

2.1 使用str.format()方法

str.format()是Python推荐的字符串格式化方法,它通过位置参数或关键字参数来替换字符串中的占位符。

# 位置参数 print("{0}的年龄是{1}岁".format("李四", 30)) # 关键字参数 print("{name}的分数是{score}".format(name="王五", score=95)) # 混合使用 print("{0}的{subject}成绩是{score}".format("赵六", score=88, subject="数学"))

格式说明符可以控制输出的对齐方式、宽度、精度等:

# 控制小数位数 pi = 3.1415926 print("PI的值是{0:.2f}".format(pi)) # 输出:PI的值是3.14 # 控制对齐和宽度 print("{:<10}".format("左对齐")) # 左对齐,宽度10 print("{:>10}".format("右对齐")) # 右对齐,宽度10 print("{:^10}".format("居中")) # 居中,宽度10

2.2 f-string格式化(Python 3.6+)

f-string是Python 3.6引入的字符串字面量格式化方法,语法更简洁,执行效率更高。

name = "张三" age = 25 print(f"{name}今年{age}岁") # 输出:张三今年25岁 # 支持表达式 a, b = 5, 10 print(f"{a} + {b} = {a + b}") # 输出:5 + 10 = 15 # 格式控制 pi = 3.1415926 print(f"PI的值是{pi:.2f}") # 输出:PI的值是3.14

2.3 旧式%格式化

虽然不推荐在新代码中使用,但许多旧代码仍使用%操作符进行格式化。

name = "李四" age = 30 print("%s今年%d岁" % (name, age)) # 输出:李四今年30岁 # 数字格式化 pi = 3.1415926 print("PI的值是%.2f" % pi) # 输出:PI的值是3.14

3. 文件操作深入

Python的文件操作功能强大,支持多种模式和操作方法。

3.1 文件打开模式详解

open()函数的mode参数决定了文件如何被打开:

模式描述
'r'只读(默认)
'w'写入,会覆盖已有文件
'x'独占创建,文件已存在则失败
'a'追加,写入内容添加到文件末尾
'b'二进制模式
't'文本模式(默认)
'+'更新(可读可写)

常见组合:

  • 'r+':读写,文件指针在开头
  • 'w+':读写,会清空文件
  • 'a+':读写,文件指针在末尾

3.2 文件读写方法

文件对象提供了多种读写方法:

# 写入文件 with open('example.txt', 'w') as f: f.write("第一行内容\n") f.write("第二行内容\n") # 读取整个文件 with open('example.txt', 'r') as f: content = f.read() print(content) # 逐行读取 with open('example.txt', 'r') as f: for line in f: print(line, end='') # 读取所有行到列表 with open('example.txt', 'r') as f: lines = f.readlines() print(lines) # ['第一行内容\n', '第二行内容\n']

3.3 文件指针操作

文件指针表示当前读写位置,可以通过tell()获取位置,通过seek()移动指针。

with open('example.txt', 'rb+') as f: print(f.tell()) # 0,初始位置 f.write(b'0123456789') print(f.tell()) # 10,写入后位置 f.seek(5) # 移动到第6个字节 print(f.read(1)) # b'5' f.seek(-3, 2) # 从文件末尾前移3个字节 print(f.read(1)) # b'8'

4. 高级输入输出技巧

4.1 上下文管理器与with语句

使用with语句可以确保文件正确关闭,即使发生异常也是如此。这是Python推荐的文件操作方式。

# 传统方式需要手动关闭文件 f = open('example.txt', 'w') try: f.write("一些内容") finally: f.close() # 使用with语句更简洁安全 with open('example.txt', 'w') as f: f.write("一些内容") # 文件会自动关闭

4.2 标准输入输出重定向

Python可以通过修改sys.stdinsys.stdoutsys.stderr来重定向标准输入输出。

import sys # 将输出重定向到文件 with open('output.txt', 'w') as f: sys.stdout = f print("这行内容会写入文件") sys.stdout = sys.__stdout__ # 恢复标准输出 print("这行内容会显示在控制台")

4.3 使用pickle进行对象序列化

pickle模块可以序列化几乎所有的Python对象,包括自定义类的实例。

import pickle class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("张三", 30) # 序列化到文件 with open('person.pkl', 'wb') as f: pickle.dump(p, f) # 从文件反序列化 with open('person.pkl', 'rb') as f: loaded_p = pickle.load(f) print(loaded_p.name, loaded_p.age) # 张三 30

4.4 JSON序列化

对于需要与其他语言交互的情况,JSON是更好的选择,Python提供了json模块。

import json data = { "name": "李四", "age": 25, "married": False, "hobbies": ["阅读", "游泳"] } # 序列化为JSON字符串 json_str = json.dumps(data, ensure_ascii=False, indent=2) print(json_str) # 写入JSON文件 with open('data.json', 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) # 从JSON文件读取 with open('data.json', 'r', encoding='utf-8') as f: loaded_data = json.load(f) print(loaded_data)

5. 实际应用案例

5.1 日志记录系统

结合文件操作和时间模块,可以创建简单的日志系统。

import datetime def write_log(message, log_file='app.log'): timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') with open(log_file, 'a') as f: f.write(f"[{timestamp}] {message}\n") write_log("程序启动") write_log("用户登录") write_log("数据处理完成")

5.2 配置文件读写

使用JSON格式存储和读取程序配置。

import json import os def load_config(config_file='config.json'): if not os.path.exists(config_file): # 默认配置 default_config = { "language": "zh-CN", "theme": "light", "font_size": 12 } with open(config_file, 'w') as f: json.dump(default_config, f, indent=2) return default_config with open(config_file, 'r') as f: return json.load(f) def save_config(config, config_file='config.json'): with open(config_file, 'w') as f: json.dump(config, f, indent=2) # 使用示例 config = load_config() print("当前语言:", config['language']) config['theme'] = 'dark' save_config(config)

5.3 数据备份与恢复

使用pickle实现应用程序数据的备份和恢复功能。

import pickle import os from datetime import datetime class DataManager: def __init__(self, data_file='data.pkl'): self.data_file = data_file self.data = self.load_data() def load_data(self): if os.path.exists(self.data_file): with open(self.data_file, 'rb') as f: return pickle.load(f) return {} def save_data(self): with open(self.data_file, 'wb') as f: pickle.dump(self.data, f) def create_backup(self): timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') backup_file = f"backup_{timestamp}.pkl" with open(backup_file, 'wb') as f: pickle.dump(self.data, f) return backup_file def restore_from_backup(self, backup_file): with open(backup_file, 'rb') as f: self.data = pickle.load(f) self.save_data() # 使用示例 manager = DataManager() manager.data['users'] = ['张三', '李四'] manager.save_data() backup_file = manager.create_backup() print(f"创建备份: {backup_file}") # 模拟数据损坏 manager.data = {} manager.save_data() # 从备份恢复 manager.restore_from_backup(backup_file) print("恢复后的数据:", manager.data)

6. 性能优化与注意事项

6.1 文件操作性能优化

处理大文件时,避免一次性读取全部内容,应使用逐行或分块读取。

# 不推荐 - 一次性读取大文件 with open('large_file.txt', 'r') as f: content = f.read() # 可能消耗大量内存 process(content) # 推荐 - 逐行处理 with open('large_file.txt', 'r') as f: for line in f: process(line) # 推荐 - 分块处理 chunk_size = 1024 * 1024 # 1MB with open('very_large_file.bin', 'rb') as f: while True: chunk = f.read(chunk_size) if not chunk: break process(chunk)

6.2 异常处理

文件操作可能引发多种异常,如文件不存在、权限不足等,应妥善处理。

try: with open('important.txt', 'r') as f: content = f.read() except FileNotFoundError: print("文件不存在") except PermissionError: print("没有权限访问文件") except IOError as e: print(f"IO错误: {e}") except Exception as e: print(f"未知错误: {e}")

6.3 编码问题

处理文本文件时,明确指定编码可以避免很多问题,推荐使用UTF-8。

# 明确指定编码 with open('multilingual.txt', 'w', encoding='utf-8') as f: f.write("中文 Español Français") with open('multilingual.txt', 'r', encoding='utf-8') as f: print(f.read())

6.4 临时文件处理

tempfile模块可以安全地创建临时文件和目录。

import tempfile # 创建临时文件 with tempfile.NamedTemporaryFile(mode='w+', suffix='.tmp', delete=False) as tmp: print(f"临时文件路径: {tmp.name}") tmp.write("临时内容") tmp.seek(0) print(tmp.read()) # 临时文件会在with块结束后自动删除(除非设置delete=False)

7. 调试与问题排查

7.1 常见问题与解决方案

问题1:文件写入后内容为空

可能原因:

  • 文件以'w'模式打开后未写入内容
  • 写入后未调用flush()或close()
  • 文件指针位置不正确

解决方案:

# 确保写入后关闭文件或使用with语句 with open('output.txt', 'w') as f: f.write("实际内容") # 或者显式调用flush() f = open('output.txt', 'w') f.write("实际内容") f.flush() # 确保内容写入磁盘 f.close()

问题2:读取文件时编码错误

可能原因:

  • 文件编码与指定的编码不匹配
  • 文件包含非法字符

解决方案:

# 尝试不同编码 encodings = ['utf-8', 'gbk', 'latin-1'] for enc in encodings: try: with open('problematic.txt', 'r', encoding=enc) as f: print(f.read()) break except UnicodeDecodeError: continue

问题3:pickle加载时出现AttributeError

可能原因:

  • 序列化和反序列化的环境不同(类定义不一致)
  • 使用了不同Python版本

解决方案:

  • 确保类定义在反序列化环境中可用
  • 对于长期存储,考虑使用JSON等更稳定的格式

7.2 调试技巧

使用repr()显示原始内容

当输出内容显示不正常时,使用repr()可以显示原始形式,包括特殊字符。

with open('weird.txt', 'r') as f: content = f.read() print("正常显示:", content) print("原始形式:", repr(content))

检查文件指针位置

文件操作不符合预期时,检查指针位置可以发现问题。

with open('example.txt', 'r+') as f: print("初始位置:", f.tell()) line = f.readline() print("读取一行后位置:", f.tell()) f.seek(0, 2) # 移动到文件末尾 print("移动到末尾后位置:", f.tell())

使用try-except捕获特定异常

精确捕获异常可以提供更有用的调试信息。

try: with open('missing.txt', 'r') as f: content = f.read() except FileNotFoundError as e: print(f"调试信息: 文件路径 - {e.filename}, 错误 - {e.strerror}") # 可以在这里添加恢复逻辑或记录日志