关注我不迷路,您的点赞+收藏,就是我坚持的动力!
引言
在Python编程中,模块和输入输出(I/O)操作是我们每天都要打交道的重要内容。
今天,我们将深入探讨如何优雅地处理文件、数据格式和异常,让你的代码更加健壮和专业!
文章目录
一、模块:Python的"乐高积木"
模块就是一个Python文件(.py),包含函数、类和变量,可以被其他Python程序导入使用。模块是基本的组织单位,让我们可以把相关功能组织在一起。模块化后,代码逻辑可以重复利用,避免命名冲突,模块内代码清晰容易维护。
模块通常使用import语句来导入模块。
常见标准库模块包括:
# 常见模块
math:提供了数学函数,如三角函数、对数、幂等。
random:用于生成随机数,包括随机选择、打乱序列等。
datetime:处理日期和时间的模块。
os:提供了与操作系统交互的功能,如文件操作、目录操作等。
sys:提供了与Python解释器交互的变量和函数。
json:用于处理JSON数据。
re:正则表达式模块,用于字符串匹配和替换。
collections:提供了额外的数据结构,如 defaultdict、Counter、deque等。
itertools:提供了用于操作迭代对象的函数。
time:提供了时间相关的函数,如 sleep、time 等。
常用第三方库包括
# 数据科学
pip install numpy pandas matplotlib scikit-learn
# numpy:科学计算库
# pandas:数据分析库
# matplotlib:绘图库
# scikit-learn:机器学习库
# 网络开发
pip install requests beautifulsoup4 flask django
# requests:HTTP库
# beautifulsoup4:解析HTML和XML文档的库
# flash:轻量级的Web应用框架
# django:高级的Web框架
# 自动化
pip install selenium opencv-python pygame
# selenium: 一个用于Web应用程序测试的工具
# opencv-python: OpenCV(的Python绑定,是一个开源的计算机视觉和机器学习软件库
# pygame: 一个用于编写视频游戏的Python模块
另:还可以自行编写一些通用化模块,供系统使用。
二、文件读写
Python中的文件读写是一个基础且重要的操作。
文件读写通常涉及打开文件、读取或写入数据、关闭文件等步骤。Python内置了open()函数用于打开文件,并返回一个文件对象。通过文件对象,我们可以调用各种方法来读写文件。
2.1 文件的基本操作
read(size): 读取指定大小的数据,如果不指定size,则读取整个文件。
readline(): 读取一行。
readlines(): 读取所有行并返回一个列表。
write(string): 写入字符串。
writelines(list): 写入一个字符串列表。
close(): 关闭文件。
# 示例
# 1. 打开文件
file = open("filename", "mode")
# 2. 读写操作
content = file.read()
# 3. 关闭文件
file.close()
# 文件的操作模式
模式 描述 文件不存在时 文件存在时 指针位置
'r' 只读(默认) 报错 正常打开 开头
'w' 写入 创建新文件 覆盖原内容 开头
'a' 追加 创建新文件 在末尾追加 末尾
'x' 独占创建 创建新文件 报错 开头
'r+' 读写 报错 正常打开 开头
'w+' 读写 创建新文件 覆盖原内容 开头
'a+' 读写 创建新文件 在末尾读写 末尾
2.2 with:上下文管理器
with语句是上下文管理器协议的一种应用,它用于简化资源管理,确保资源在使用后被正确释放。
上下文管理器是实现了__enter__和__exit__方法的对象。
当执行with语句时,会先调用__enter__方法,然后执行with语句块中的代码,最后无论是否发生异常,都会调用__exit__方法。
使用with语句的好处是,即使代码块中发生了异常,__exit__方法也会被调用,从而可以执行清理操作(比如关闭文件)。
# 传统方法
file = None
try:
file = open("example.txt", "w", encoding="utf-8")
file.write("Hello, World!\n")
file.write("这是第二行\n")
except IOError as e:
print(f"文件操作错误: {e}")
finally:
if file:
file.close()
# 自动管理资源,确保文件正确关闭
with open("example.txt", "a", encoding="utf-8") as f:
f.write("这是追加的内容\n")
# 离开with块后文件自动关闭
# 读写文件
with open("example.txt", "a+", encoding="utf-8") as f:
f.write("这是追加的内容\n")
# 重置文件指针
f.seek(0)
# 读取整个文件
content = f.read()
print("文件内容:")
print(content)
# 重置文件指针
f.seek(0)
# 逐行读取
print("\n逐行读取:")
for i, line in enumerate(f, 1):
print(f"第{i}行: {line.strip()}")
大文件处理技巧:
1)逐块读取
2)逐行读取
# 逐块读取
with open(input_file, "rb") as infile, open(output_file, "wb") as outfile:
while True:
chunk = infile.read(chunk_size)
if not chunk: # 如果读取到的数据为空
break
# 处理数据块(这里只是简单复制)
outfile.write(chunk)
# 逐行读取
line_count = 0
word_count = 0
with open(filepath, "r", encoding=encoding) as f:
for line in f:
line_count += 1
word_count += len(line.split())
# 每处理10000行输出一次进度
if line_count % 10000 == 0:
print(f"已处理 {line_count} 行,{word_count} 个单词")
三、输入输出
3.1 标准输入输出
标准输入使用input函数来读取用户输入
# 单个输入
name = input("请输入您的姓名:")
print(f"你好,{name}!")
# 多个输入
age = input("请输入您的年龄:")
city = input("请输入您的城市:")
print(f"信息:{name}, {age}岁, 来自{city}")
# 输入值类型转换
num1 = int(input("请输入第一个数字:"))
num2 = int(input("请输入第二个数字:"))
print(f"两个数字的和:{num1 + num2}")
标准输入使用print函数来进行输出
# 基本输出
print("Hello, World!")
# 输出多个值(默认用空格分隔)
print("Python", "Java", "C++") # Python Java C++
# 修改分隔符
print("Python", "Java", "C++", sep=", ") # Python, Java, C++
# 修改结束符(默认换行)
print("Hello", end=" ") # 不换行,以空格结束
print("World") # Hello World
# 格式化输出
name = "张三"
score = 95.5
print(f"学生:{name},分数:{score:.1f}") # f-string
print("学生:{},分数:{:.1f}".format(name, score)) # format方法
print("学生:%s,分数:%.1f" % (name, score)) # %格式化
# 输出均为:学生:张三,分数:95.5
3.2 输入输出的高级用法
1)sys 模块
sys模块是Python标准库中的一个内置模块,它提供了与Python解释器及其环境(如命令行参数、标准输入输出、错误流、退出程序等)进行交互的变量和函数。
sys.stdin 读取输入
sys.stdout 输出显示
import sys
# 读取单行输入
data = sys.stdin.readline().strip() # 读取一行,去除换行符
print(f"读取到:{data}")
# 读取所有输入(直到EOF)
print("请输入内容(Ctrl+D结束):")
all_input = sys.stdin.read()
print(f"读取的全部内容:\n{all_input}")
# 逐行读取
print("请输入多行内容(Ctrl+D结束):")
lines = sys.stdin.readlines()
print(f"共读取 {len(lines)} 行:")
for i, line in enumerate(lines, 1):
print(f"第{i}行:{line.strip()}")
2)交互式输入
getpass:密码输入库
# 输入验证循环
while True:
try:
age = int(input("请输入年龄(0-120):"))
if 0 <= age <= 120:
break
else:
print("年龄必须在0-120之间!")
except ValueError:
print("请输入有效的数字!")
print(f"您的年龄是:{age}")
# 密码输入(隐藏输入内容)
import getpass
password = getpass.getpass("请输入密码:")
print(f"密码长度:{len(password)}")
3) 进度条显示
import sys
import time
# 简单进度条
def progress_bar(iteration, total, length=50):
percent = 100 * (iteration / total)
filled_length = int(length * iteration // total)
bar = '█' * filled_length + '-' * (length - filled_length)
sys.stdout.write(f'\r进度:|{bar}| {percent:.1f}% ') # 行首输出
sys.stdout.flush() # 立即刷新缓冲区
# 使用示例
total_items = 100
for i in range(total_items + 1):
time.sleep(0.05) # 模拟工作
progress_bar(i, total_items)
print() # 换行
!! print() 会自动添加换行符,sys.stdout.write()不会,使用\n才能换行。
3.3 处理大文件和流
1)分块读取 和 逐行读取
import sys
# 分块读取大文件(避免内存不足)
chunk_size = 1024 # 1KB
total_bytes = 0
print("开始读取标准输入(Ctrl+D结束)...")
while True:
chunk = sys.stdin.read(chunk_size)
if not chunk: # 如果读取到的数据为空,代表到了文件尾端
break
total_bytes += len(chunk)
print(f"总共读取 {total_bytes} 字节")
# 逐行处理大文件
line_count = 0
for line in sys.stdin:
line_count += 1
# 处理每一行
processed_line = line.strip().upper()
sys.stdout.write(f"第{line_count}行:{processed_line}\n")
print(f"总共处理 {line_count} 行")
2)缓冲和非缓冲I/O
import sys
# 设置缓冲区大小
sys.stdout = open('buffered.txt', 'w', buffering=2048) # 2KB缓冲区
# 无缓冲输出(立即写入)
sys.stderr = open('unbuffered.txt', 'w', buffering=0)
# 行缓冲(遇到换行符立即写入)
sys.stdout = open('linebuffered.txt', 'w', buffering=1)
# 手动刷新缓冲区
print("这条消息在缓冲区")
sys.stdout.flush() # 立即写入
print("这条消息也会在缓冲区")
四、异常处理的最佳实践
4.1 基础异常处理Try-Except
def basic_exception_handling():
# 1. 最基本的try-except
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"捕获到除零错误: {e}")
# 2. 捕获多个异常
try:
num = int("abc")
result = 10 / num
except (ValueError, ZeroDivisionError) as e:
print(f"捕获到数值错误: {e}")
# 3. 分别处理不同异常
try:
file = open("nonexistent.txt", "r")
content = file.read()
except FileNotFoundError as e:
print(f"文件未找到: {e}")
except IOError as e:
print(f"I/O错误: {e}")
except Exception as e:
print(f"其他错误: {e}")
finally:
print("无论是否发生异常,都会执行这里")
# 4. 使用else子句
try:
data = {"key": "value"}
value = data["key"]
except KeyError as e:
print(f"键不存在: {e}")
else:
print(f"操作成功,获取的值: {value}")
finally:
print("清理工作完成")
4.2 自定义异常
# 自定义异常类
# 验证错误
class ValidationError(Exception):
def __init__(self, message, field=None, value=None):
self.message = message
self.field = field
self.value = value
super().__init__(self.message)
def __str__(self):
if self.field:
return f"{self.message} (字段: {self.field}, 值: {self.value})"
return self.message
# 数据库错误
class DatabaseError(Exception):
def __init__(self, message, query=None, params=None):
self.message = message
self.query = query
self.params = params
super().__init__(self.message)
def __str__(self):
details = []
if self.query:
details.append(f"查询: {self.query}")
if self.params:
details.append(f"参数: {self.params}")
if details:
return f"{self.message} ({'; '.join(details)})"
return self.message
# 使用自定义异常
# 验证用户数据
def validate_user_data(data):
if "username" not in data:
raise ValidationError("用户名不能为空", field="username")
if len(data.get("username", "")) < 3:
raise ValidationError("用户名至少3个字符", field="username", value=data.get("username"))
if "email" not in data or "@" not in data["email"]:
raise ValidationError("邮箱格式不正确", field="email", value=data.get("email"))
return True
# 用户注册流程
def process_user_registration(user_data):
try:
validate_user_data(user_data)
print("用户数据验证通过")
# 模拟数据库操作
raise DatabaseError("插入数据失败", query="INSERT INTO users", params=user_data)
except ValidationError as e:
print(f"数据验证失败: {e}")
# 可以记录日志、返回错误信息等
return {"success": False, "error": str(e)}
except DatabaseError as e:
print(f"数据库操作失败: {e}")
return {"success": False, "error": "数据库错误"}
except Exception as e:
print(f"未知错误: {e}")
return {"success": False, "error": "系统错误"}
else:
return {"success": True, "message": "注册成功"}
finally:
print("注册流程结束")
# 测试
test_data = {"username": "ab", "email": "invalid"}
result = process_user_registration(test_data)
print(f"结果: {result}")
五、高频面试题解析
问题1:with语句的工作原理是什么?
with语句的背后是上下文管理器协议,任何实现了__enter__和__exit__方法的对象都可以作为上下文管理器。
1)with语句确保资源被正确释放
2)enter返回的对象被as接收
3)exit在退出时调用,处理异常
4)内置的open()函数返回的文件对象就是上下文管理器
class MyContext:
def __enter__(self):
print("进入上下文")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文")
if exc_type is not None:
print(f"发生异常: {exc_val}")
# 返回True表示异常已处理,不再向上抛出
return False
def do_something(self):
print("执行操作")
# 使用
with MyContext() as ctx:
ctx.do_something()
# 这里如果发生异常,会在__exit__中处理
# 等同于:
ctx = MyContext()
ctx.__enter__()
try:
ctx.do_something()
except Exception as e:
ctx.__exit__(type(e), e, e.__traceback__)
raise
else:
ctx.__exit__(None, None, None)
问题2:Python中如何处理大文件,避免内存溢出?
1)文本文件使采用逐行读取:for line in file
with open("large_file.txt", "r", encoding="utf-8") as f:
for line in f: # 一次只读取一行到内存
process_line(line)
2)二进制文件采用分块读取:用指定大小的chunk读取
chunk_size = 1024 * 1024 # 1MB
with open("large_file.bin", "rb") as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
process_chunk(chunk)
3)使用生成器处理:实现惰性加载
def read_large_file(filepath, chunk_size=1024):
with open(filepath, "rb") as f:
while True:
data = f.read(chunk_size)
if not data:
break
yield data
# 使用生成器
for chunk in read_large_file("large_file.bin"):
process_chunk(chunk)
4)超大文件考虑使用mmap(内存映射文件)
import mmap
with open("large_file.bin", "r+b") as f:
# 创建内存映射
mm = mmap.mmap(f.fileno(), 0)
# 像操作字节数组一样操作文件
data = mm[1000:2000] # 只读取指定范围
mm.close()
问题3:Python中json.loads()和json.load()有什么区别?
loads字符串加载成对象类,load从文件中加载成对象类
dumps将字符串对象写入到文件中,dump将python对象写入文件中
1)loads/dumps:处理字符串
2)load/dump:处理文件对象
3)load和loads方法都有对应的参数控制编码、缩进等
4)设置ensure_ascii=False支持中文
import json
# json.loads() 从字符串加载 load string
json_string = '{"name": "张三", "age": 25}'
data_from_string = json.loads(json_string)
print(data_from_string) # {'name': '张三', 'age': 25}
# json.load() 从文件对象加载
with open("data.json", "r", encoding="utf-8") as f:
data_from_file = json.load(f)
print(data_from_file)
# 对应的保存方法:
# json.dumps() 将对象转换为字符串
json_str = json.dumps({"name": "张三", "age": 25}, ensure_ascii=False)
print(json_str) # {"name": "张三", "age": 25}
# json.dump() 将对象保存到文件
with open("output.json", "w", encoding="utf-8") as f:
json.dump({"name": "张三", "age": 25}, f, ensure_ascii=False, indent=2)
六、总结与最佳实践
核心要点回顾
模块化开发:合理组织代码,提高复用性
文件操作:使用with语句确保资源正确释放
异常处理:精确捕获异常,提供有用的错误信息
输入输出:灵活处理各种I/O场景
最佳实践建议
✅ 推荐做法:
使用pathlib处理文件路径,更直观安全
处理大文件时,使用生成器或分块、分行读取
为自定义异常提供有用的错误信息
使用json.dump/load时指定ensure_ascii=False支持中文
❌ 避免做法:
不要用字符串拼接处理文件路径
不要一次性读取大文件到内存
不要忽略文件编码(默认使用utf-8)
不要在没有检查的情况下覆盖文件
相关实战小游戏见代码篇: 简易文件管理器
下期预告
下一篇我们将深入学习Python函数。
学习函数是培养编程思维和软件工程能力的基础。
函数是构建程序的基本模块,是写出高质量代码的关键。
如果觉得有帮助,请关注+点赞+收藏,这是对我最大的鼓励!
如有问题,请评论区留言

被折叠的 条评论
为什么被折叠?



