Python 第十三节 Python中各种输入输出方案详解及注意事项
前言
Python
中各种输入输出使用方案,如:包括表达式语句、print()
函数等,以及str()
、repr()
转换函数和字符串对齐填充方法,还讲解了str.format()
格式化输出和旧式%操作符用法。还涉及键盘输入的input()函数,文件读写的open()函数及多种模式,文件对象的读写、指针操作等方法
1. 基本输入输出函数
1.1 标准输入输出
input()
函数
# 基本用法name = input("请输入您的姓名: ")print(f"你好, {name}!")# 类型转换age = int(input("请输入您的年龄: "))height = float(input("请输入您的身高(米): "))print(f"年龄: {age}, 身高: {height}")print() 函数
# 基本输出print("Hello, World!")# 输出多个值name = "Andy"age = 18print("姓名:", name, "年龄:", age)# 格式化输出print(f"姓名: {name}, 年龄: {age}")print("姓名: {}, 年龄: {}".format(name, age))print("姓名: %s, 年龄: %d" % (name, age))# 控制分隔符和结束符print("Python", "Java", "C++", sep=" | ", end="\n---\n")
1.2 格式化输出详解
f-string
(Python 3.6+)
name = "Bob"age = 30salary = 5000.50# 基本用法print(f"{name} is {age} years old")# 数字格式化print(f"工资: {salary:.2f}") # 保留2位小数print(f"年龄: {age:05d}") # 5位数字,前面补零print(f"十六进制: {age:#x}") # 十六进制print(f"百分比: {0.75:.1%}") # 百分比# 表达式计算a, b = 5, 3print(f"{a} + {b} = {a + b}")print(f"{a} × {b} = {a * b}")str.format() 方法
# 位置参数print("{0} 喜欢 {1} 和 {2}".format("小明", "Python", "Java"))print("{1} 在 {0} 之前".format("B", "A"))# 关键字参数print("姓名: {name}, 年龄: {age}".format(name="Alice", age=25))# 混合使用print("{0} 的 {item} 价格是 {price:.2f}".format("商店", item="苹果", price=5.99))# 对齐和填充print("{:>10}".format("右对齐")) # 右对齐,宽度10print("{:<10}".format("左对齐")) # 左对齐,宽度10print("{:^10}".format("居中")) # 居中,宽度10print("{:*^10}".format("居中")) # 居中,用*填充
2. 文件输入输出
2.1 文件基本操作
打开和关闭文件
# 基本文件写入
with open('example.txt', 'w', encoding='utf-8') as file:file.write("Hello, World!\n")file.write("这是第二行\n")# 基本文件读取
with open('example.txt', 'r', encoding='utf-8') as file:content = file.read()print(content)# 不使用 with 语句(不推荐)
file = open('example.txt', 'r')
try:content = file.read()
finally:file.close()
文件打开模式
常用如下:
‘r’ :只读(默认)
‘r+’:可读可写
‘w’ :写入,会覆盖已有文件
‘w+’:打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件
‘x’ :排他性创建,文件已存在则失败
‘a’ :追加,在文件末尾添加
‘b’ :二进制模式
‘t’ :文本模式(默认)
‘+’ :更新(可读可写)
2.2 文件读取方法
# 读取整个文件
with open('example.txt', 'r', encoding='utf-8') as file:content = file.read()print("整个文件内容:")print(content)# 逐行读取
with open('example.txt', 'r', encoding='utf-8') as file:print("逐行读取:")line = file.readline()while line:print(line.strip()) # strip() 去除换行符line = file.readline()# 读取所有行到列表
with open('example.txt', 'r', encoding='utf-8') as file:lines = file.readlines()print("所有行:")# enumerate(sequence, [start=0]) 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中# sequence 一个序列、迭代器或其他支持迭代对象# start 下标起始位置的值for i, line in enumerate(lines, 1):print(f"第{i}行: {line.strip()}")# 使用迭代器逐行读取(推荐用于大文件)
with open('example.txt', 'r', encoding='utf-8') as file:print("使用迭代器:")for line_num, line in enumerate(file, 1):print(f"第{line_num}行: {line.strip()}")
2.3 文件写入方法
# 写入字符串
with open('output.txt', 'w', encoding='utf-8') as file:file.write("这是第一行\n")file.write("这是第二行\n")# 写入多行
lines = ["第一行\n", "第二行\n", "第三行\n"]
with open('output.txt', 'w', encoding='utf-8') as file:file.writelines(lines)# 追加模式
with open('output.txt', 'a', encoding='utf-8') as file:file.write("这是追加的内容\n")# 批量写入数据
data = [{"name": "Alice", "age": 25, "city": "Beijing"},{"name": "Bob", "age": 30, "city": "Shanghai"},{"name": "Charlie", "age": 35, "city": "Guangzhou"}
]with open('data.csv', 'w', encoding='utf-8') as file:file.write("姓名,年龄,城市\n")for person in data:file.write(f"{person['name']},{person['age']},{person['city']}\n")
3. 二进制文件操作
# 二进制写入
with open('binary_data.bin', 'wb') as file:file.write(b'\x48\x65\x6c\x6c\x6f') # "Hello" 的二进制# 二进制读取
with open('binary_data.bin', 'rb') as file:data = file.read()print("二进制数据:", data)print("转换为字符串:", data.decode('utf-8'))# 图片文件复制
def copy_image(source_path, target_path):try:with open(source_path, 'rb') as source:with open(target_path, 'wb') as target:# 分块读取大文件while True:chunk = source.read(4096) # 每次读取4KBif not chunk:breaktarget.write(chunk)print("文件复制成功!")except FileNotFoundError:print("文件不存在!")except Exception as e:print(f"发生错误: {e}")# 使用示例
copy_image('source.jpg', 'copy.jpg')
4. JSON 文件操作
import json# 数据准备
data = {"employees": [{"name": "Alice", "age": 25, "department": "IT"},{"name": "Bob", "age": 30, "department": "HR"},{"name": "Charlie", "age": 35, "department": "Finance"}],"company": "Tech Corp"
}# 写入 JSON 文件
with open('data.json', 'w', encoding='utf-8') as file:json.dump(data, file, ensure_ascii=False, indent=2)# 读取 JSON 文件
with open('data.json', 'r', encoding='utf-8') as file:loaded_data = json.load(file)print("JSON 数据:")print(json.dumps(loaded_data, indent=2, ensure_ascii=False))# JSON 字符串操作
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print("JSON 字符串:")
print(json_str)# 从字符串加载
parsed_data = json.loads(json_str)
print("解析后的数据:", parsed_data['company'])
5. CSV 文件操作
import csv# 写入 CSV 文件
data = [['姓名', '年龄', '城市', '工资'],['Alice', '25', '北京', '5000'],['Bob', '30', '上海', '6000'],['Charlie', '35', '广州', '7000']
]with open('employees.csv', 'w', encoding='utf-8', newline='') as file:writer = csv.writer(file)writer.writerows(data)# 读取 CSV 文件
with open('employees.csv', 'r', encoding='utf-8') as file:reader = csv.reader(file)print("CSV 文件内容:")for row in reader:print(row)# 使用字典方式读写 CSV
employees = [{'name': 'Alice', 'age': 25, 'city': 'Beijing', 'salary': 5000},{'name': 'Bob', 'age': 30, 'city': 'Shanghai', 'salary': 6000},{'name': 'Charlie', 'age': 35, 'city': 'Guangzhou', 'salary': 7000}
]# 字典写入
with open('employees_dict.csv', 'w', encoding='utf-8', newline='') as file:fieldnames = ['name', 'age', 'city', 'salary']writer = csv.DictWriter(file, fieldnames=fieldnames)writer.writeheader()writer.writerows(employees)# 字典读取
with open('employees_dict.csv', 'r', encoding='utf-8') as file:reader = csv.DictReader(file)print("字典方式读取:")for row in reader:print(f"{row['name']} - {row['city']} - ¥{row['salary']}")
6. 高级输入输出技巧
6.1 上下文管理器与自定义输出
class TeeOutput:"""同时输出到控制台和文件"""def __init__(self, filename):self.file = open(filename, 'w', encoding='utf-8')self.stdout = sys.stdoutdef write(self, text):self.file.write(text)self.stdout.write(text)def flush(self):self.file.flush()self.stdout.flush()def close(self):self.file.close()# 使用示例
import sys# 保存原来的标准输出
original_stdout = sys.stdouttry:# 重定向输出tee = TeeOutput('output.log')sys.stdout = teeprint("这行会同时显示在控制台和文件中")print("另一行输出")finally:# 恢复标准输出sys.stdout = original_stdouttee.close()
6.2 进度条显示
import time
import sysdef progress_bar(iteration, total, prefix='', suffix='', length=50, fill='█'):"""显示进度条"""percent = f"{100 * (iteration / float(total)):.1f}"filled_length = int(length * iteration // total)bar = fill * filled_length + '-' * (length - filled_length)print(f'\r{prefix} |{bar}| {percent}% {suffix}', end='\r')if iteration == total:print()# 使用示例
total_items = 100
for i in range(total_items + 1):time.sleep(0.05) # 模拟工作progress_bar(i, total_items, prefix='进度:', suffix='完成')
7. 注意事项和最佳实践
7.1 文件操作注意事项
# 1. 始终使用 with 语句# ❌ 不推荐file = open('test.txt', 'r')content = file.read()file.close() # 可能忘记关闭# ✅ 推荐with open('test.txt', 'r') as file:content = file.read()# 2. 处理文件不存在的情况try:with open('nonexistent.txt', 'r') as file:content = file.read()except FileNotFoundError:print("文件不存在!")except PermissionError:print("没有文件访问权限!")except Exception as e:print(f"读取文件时发生错误: {e}")# 3. 指定文件编码# ❌ 可能在不同系统上出现编码问题with open('file.txt', 'r') as file:content = file.read()# ✅ 明确指定编码with open('file.txt', 'r', encoding='utf-8') as file:content = file.read()# 4. 大文件处理def process_large_file(filename):"""处理大文件的正确方式"""with open(filename, 'r', encoding='utf-8') as file:for line in file: # 逐行读取,内存友好process_line(line.strip())# 5. 路径处理import osfrom pathlib import Path# 使用 pathlib(现代方式)file_path = Path('data') / 'subfolder' / 'file.txt'with open(file_path, 'w') as file:file.write("内容")# 检查文件是否存在if file_path.exists():print("文件存在")
7.2 输入验证和安全
def get_valid_input(prompt, input_type=str, validation_func=None):"""获取有效的用户输入Args:prompt: 提示信息input_type: 输入类型validation_func: 自定义验证函数"""while True:try:user_input = input(prompt)if input_type != str:user_input = input_type(user_input)if validation_func and not validation_func(user_input):raise ValueError("输入值不符合要求")return user_inputexcept ValueError as e:print(f"输入无效: {e},请重新输入")# 使用示例
# 获取年龄(1-150之间)
age = get_valid_input("请输入年龄: ", int, lambda x: 1 <= x <= 150
)# 获取非空字符串
name = get_valid_input("请输入姓名: ",validation_func=lambda x: len(x.strip()) > 0
)print(f"姓名: {name}, 年龄: {age}")
8. 实际应用案例
8.1 配置文件管理
import configparser
import jsonclass ConfigManager:"""配置文件管理器"""def __init__(self, config_file='config.ini'):self.config_file = config_fileself.config = configparser.ConfigParser()def load_config(self):"""加载配置"""try:self.config.read(self.config_file, encoding='utf-8')except Exception as e:print(f"加载配置文件失败: {e}")def save_config(self):"""保存配置"""try:with open(self.config_file, 'w', encoding='utf-8') as file:self.config.write(file)except Exception as e:print(f"保存配置文件失败: {e}")def get_setting(self, section, key, default=None):"""获取配置项"""try:return self.config.get(section, key)except (configparser.NoSectionError, configparser.NoOptionError):return default# 使用示例
config = ConfigManager()
config.load_config()database_host = config.get_setting('Database', 'host', 'localhost')
database_port = config.get_setting('Database', 'port', '3306')print(f"数据库连接: {database_host}:{database_port}")
8.2 日志记录系统
import logging
from datetime import datetimedef setup_logging(log_file='app.log'):"""设置日志系统"""# 创建日志器logger = logging.getLogger('MyApp')logger.setLevel(logging.DEBUG)# 避免重复添加处理器if not logger.handlers:# 文件处理器file_handler = logging.FileHandler(log_file, encoding='utf-8')file_handler.setLevel(logging.DEBUG)# 控制台处理器console_handler = logging.StreamHandler()console_handler.setLevel(logging.INFO)# 格式化器formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')file_handler.setFormatter(formatter)console_handler.setFormatter(formatter)# 添加处理器logger.addHandler(file_handler)logger.addHandler(console_handler)return logger# 使用示例
logger = setup_logging()logger.info("应用程序启动")
logger.debug("调试信息")
logger.warning("警告信息")
logger.error("错误信息")
总结
关键要点:
输入处理:使用 input()
获取用户输入,注意类型转换和验证
输出格式化:优先使用 f-string
,其次是 str.format()
文件操作:始终使用 with 语句,明确指定编码
异常处理:合理处理文件操作可能出现的异常
大文件处理:使用迭代方式逐行或分块处理
数据持久化:根据数据类型选择合适的格式(JSON、CSV
、二进制等)
最佳实践:
- 使用
pathlib
处理文件路径 - 为文本文件明确指定编码(
推荐 UTF-8
) - 使用日志模块代替简单的
print()
进行调试和记录 - 对用户输入进行充分的验证和清理
- 在处理敏感数据时注意安全性
这些输入输出方法是 Python 编程的基础,熟练掌握它们对于开发各种应用程序至关重要。