前言
在Python 3中,输入与输出是程序与外界交互的重要方式。无论是读取用户输入、打印结果,还是处理文件,Python 3提供了一组强大且直观的工具。从最基本的控制台输入输出到复杂的文件操作、数据序列化,Python的I/O系统涵盖了几乎所有开发场景的需求。本文将系统性地总结Python 3的输入与输出方法,帮助您从入门到精通全面掌握这一核心技能。
第一章:基础输入
1.1 input() 函数的基本用法
在Python 3中,input() 函数用于从用户获取输入。与Python 2中的raw_input()不同,input()会将用户输入的内容作为字符串返回。
基本语法:
input([prompt]) # prompt是可选的提示信息
示例:
name = input("请输入你的名字: ")
print(f"你好, {name}!")
当程序执行到input()时,会暂停执行,等待用户在键盘上输入数据,并在用户按下回车键后继续执行。这个特性使得input()非常适合用于交互式命令行应用。
1.2 输入类型转换
由于input()始终返回字符串类型,在处理数值输入时必须进行类型转换:
age = int(input("请输入你的年龄: ")) # 转换为整数
height = float(input("请输入你的身高(米): ")) # 转换为浮点数
price = float(input("请输入价格: ")) # 转换为浮点数
如果不进行类型转换,直接对输入进行数学运算会导致类型错误。例如:
# 错误的做法
age = input("请输入年龄: ")
print("明年你将会是", age + 1, "岁") # 报错:不能将字符串和整数相加
# 正确的做法
age = int(input("请输入年龄: "))
print(f"明年你将会是 {age + 1} 岁")
1.3 多值输入处理
在实际开发中,经常需要在一行内输入多个值。Python提供了灵活的解决方案:
使用split()方法处理空格分隔的输入:
# 输入多个值用空格分隔
values = input("请输入多个数字(空格分隔): ").split()
numbers = [int(x) for x in values]
print("你输入的数字是:", numbers)
使用自定义分隔符:
# 用逗号分隔的输入
values = input("请输入多个数字(逗号分隔): ").split(',')
numbers = [int(v) for v in values]
print("你输入的数字是:", numbers)
使用map()函数进行批量转换:
# 一行代码完成输入和类型转换
nums = list(map(int, input().split())) # 如输入 "1 2 3" → [1, 2, 3]
1.4 多行输入处理
在某些场景下,需要处理多行输入,比如读取大量数据或交互式对话:
使用循环读取多行输入:
lines = []
while True:
try:
line = input()
if not line: # 空行退出
break
lines.append(line)
except EOFError: # Ctrl+D (Unix) 或 Ctrl+Z (Windows) 退出
break
print("你输入的内容是:")
for line in lines:
print(line)
1.5 输入验证
在实际应用中,用户输入可能不符合预期,因此输入验证至关重要:
while True:
try:
age = int(input("请输入年龄(1-120): "))
if 1 <= age <= 120:
break
else:
print("请输入有效年龄!")
except ValueError:
print("请输入数字!")
这个例子展示了如何结合异常处理和条件判断来确保用户输入的有效性。
1.6 高级输入:eval()函数
eval()函数可以将字符串作为Python表达式进行求值:
n = eval(input())
print(n)
# 输入: 5+2
# 输出: 7
注意:eval()存在安全风险,因为它会执行任意Python代码。在生产环境中应谨慎使用,或使用更安全的替代方案。
1.7 命令行参数输入
除了交互式输入,Python还可以通过命令行参数获取输入:
import sys
if len(sys.argv) != 3:
print("用法: python script.py <参数1> <参数2>")
sys.exit(1)
param1 = sys.argv
param2 = sys.argv
print(f"参数1: {param1}, 参数2: {param2}")
这种方式适用于批处理和自动化脚本场景。
第二章:基础输出
2.1 print() 函数基础
print()是Python中最基本的输出函数,用于将内容输出到标准输出(通常是控制台)。
基本语法:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
参数说明:
*objects:要打印的对象,可以是多个,以逗号分隔sep:对象间的分隔符,默认为空格end:行末尾的字符,默认为换行符\nfile:写入的文件对象,默认为sys.stdoutflush:是否强制刷新文件流
2.2 基本输出示例
# 基本输出
print("Hello, World!") # 输出: Hello, World!
# 输出多个值
print("Python", 3.9, "is awesome!") # 输出: Python 3.9 is awesome!
2.3 使用sep参数自定义分隔符
print("2023", "03", "15", sep="-") # 输出: 2023-03-15
print("Python", "is", "awesome", sep="-") # 输出: Python-is-awesome
print("Alice", "Bob", "Charlie", sep=", ") # 输出: Alice, Bob, Charlie
2.4 使用end参数控制行尾
print("Hello", end=" ")
print("World!") # 输出: Hello World!
# 构建进度条效果
import time
for i in range(10):
print(f"\r进度: {i*10}%", end="", flush=True)
time.sleep(0.1)
print("\r进度: 100%")
2.5 输出到文件
with open('output.txt', 'w') as f:
print("This goes to a file", file=f)
print("第二行内容", file=f)
2.6 格式化输出
Python提供了多种格式化字符串的方法:
使用f-string(推荐,Python 3.6+):
name = "Alice"
age = 25
print(f"{name} is {age} years old.")
print(f"{name} is {age} years old and will be {age + 1} next year.")
使用str.format()方法:
print("{} is {} years old.".format("Alice", 25))
print("{0} is {1} years old. {0} likes Python.".format("Alice", 25))
print("Name: {name}, Age: {age}".format(name="Bob", age=30))
使用%格式化(旧式):
print("%s is %d years old." % ("Alice", 25))
print("Name: %s, Age: %d" % ("Bob", 30))
2.7 数字格式化
pi = 3.1415926535
# 保留2位小数
print(f"π的值是: {pi:.2f}") # 输出: π的值是: 3.14
# 科学计数法
print(f"{pi:.2e}") # 输出: 3.14e+00
# 百分比
score = 0.8567
print(f"正确率: {score:.1%}") # 输出: 正确率: 85.7%
# 指定宽度和对齐
print(f"{'Name':<10}{'Age':>5}")
print(f"{'Alice':<10}{25:>5}")
2.8 转义字符与repr()
当需要调试或显示对象的精确表示时,可以使用repr()函数:
value = 42
print(repr(value)) # 输出: 42
# repr()与f-string结合
print(f"The result is {value!r}")
# repr()可以转义字符串中的特殊字符
hello = 'hello, world\n'
print(repr(hello)) # 输出: 'hello, world\n'
str()和repr()的区别:
str():返回用户易读的表达形式repr():产生解释器易读的表达形式
第三章:文件操作
3.1 文件打开与关闭
Python使用open()函数进行文件操作,推荐使用with语句自动管理资源:
基本语法:
open(filename, mode, encoding=None)
常用模式:
| 模式 | 说明 |
|---|---|
'r' | 读取(默认) |
'w' | 写入(会覆盖已有文件) |
'a' | 追加 |
'x' | 创建新文件 |
'b' | 二进制模式 |
't' | 文本模式(默认) |
'+' | 读写模式 |
推荐使用with语句:
with open('example.txt', 'w', encoding='utf-8') as f:
f.write("这是第一行\n")
f.write("这是第二行\n")
# 退出with块后自动关闭文件
3.2 文件读取方法
读取整个文件:
with open('example.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content)
逐行读取:
with open('example.txt', 'r', encoding='utf-8') as f:
for line in f:
print(line.strip()) # strip()去除换行符
读取所有行到列表:
with open('example.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
print(lines)
读取指定字节数:
with open('example.txt', 'rb') as f:
content = f.read(100) # 读取前100个字节
print(content)
3.3 文件写入方法
# 写入(覆盖模式)
with open('output.txt', 'w', encoding='utf-8') as f:
f.write("Hello, Python!\n")
f.write("第二行内容")
# 追加模式
with open('output.txt', 'a', encoding='utf-8') as f:
f.write("\n这是追加的内容")
3.4 文件指针操作
with open('example.txt', 'rb') as f:
# 获取当前指针位置
pos = f.tell()
print(f"当前位置: {pos}")
# 移动指针到指定位置
f.seek(10) # 从开头移动10个字节
print(f.read(5))
# 从当前位置移动
f.seek(5, 1) # 从当前位置向后5个字节
# 从文件末尾移动
f.seek(-10, 2) # 从文件末尾向前10个字节
3.5 文件状态检查
import os
# 检查文件是否存在
if os.path.exists('example.txt'):
print("文件存在")
# 获取文件大小
size = os.path.getsize('example.txt')
print(f"文件大小: {size}字节")
# 获取文件修改时间
import datetime
mtime = os.path.getmtime('example.txt')
print(f"修改时间: {datetime.datetime.fromtimestamp(mtime)}")
# 重命名文件
os.rename('example.txt', 'new_example.txt')
# 删除文件
os.remove('new_example.txt')
3.6 大文件处理策略
处理大文件时,应避免一次性读取到内存:
# 逐行处理大文件
with open('large_file.txt', 'r', encoding='utf-8') as f:
for line in f:
process_line(line) # 逐行处理
# 分块读取
with open('large_file.txt', 'rb') as f:
while True:
chunk = f.read(1024 * 1024) # 每次读取1MB
if not chunk:
break
process_chunk(chunk)
3.7 异常处理
try:
with open('nonexistent.txt', 'r') as f:
content = f.read()
except FileNotFoundError:
print("文件未找到!")
except PermissionError:
print("没有权限访问该文件!")
except Exception as e:
print(f"发生错误: {e}")
第四章:高级I/O操作
4.1 使用StringIO进行内存文件操作
StringIO允许在内存中模拟文件操作,无需实际创建磁盘文件:
from io import StringIO
# 创建内存文件对象
memory_file = StringIO()
memory_file.write("内存中的第一行\n")
memory_file.write("内存中的第二行\n")
# 读取内容
memory_file.seek(0) # 将指针移到文件开头
print(memory_file.read())
# 从字符串初始化
memory_file2 = StringIO("Hello\nWorld\n")
print(memory_file2.read())
4.2 使用BytesIO进行二进制内存操作
from io import BytesIO
# 创建二进制内存对象
bio = BytesIO()
bio.write(b'Hello, ')
bio.write(b'World!')
# 获取内容
bio.seek(0)
print(bio.read())
4.3 使用pickle进行对象序列化
pickle可以将几乎任何Python对象转换为字节流:
import pickle
data = {
'name': 'Alice',
'age': 25,
'scores': [88, 92, 95],
'metadata': {'version': 1.0, 'created': '2023-01-01'}
}
# 序列化到文件
with open('data.pkl', 'wb') as f:
pickle.dump(data, f)
# 从文件反序列化
with open('data.pkl', 'rb') as f:
loaded_data = pickle.load(f)
print(loaded_data)
注意事项:
- 使用二进制模式(
'wb'/'rb') - pickle文件是Python特有的,不与其他语言兼容
- 不要从不可信源加载pickle数据,存在安全风险
4.4 使用json进行数据交换
JSON是跨语言的数据交换格式:
import json
data = {
'name': 'Alice',
'age': 25,
'scores': [88, 92, 95],
'is_student': True
}
# 写入JSON文件
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
# 读取JSON文件
with open('data.json', 'r', encoding='utf-8') as f:
loaded_data = json.load(f)
print(loaded_data)
# 字符串操作
json_str = json.dumps(data, indent=2)
print(json_str)
data_dict = json.loads(json_str)
4.5 使用csv模块处理表格数据
import csv
# 写入CSV
data = [
["Name", "Age", "City"],
["Alice", 30, "New York"],
["Bob", 25, "Los Angeles"],
["Charlie", 35, "Chicago"]
]
with open('data.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerows(data)
# 读取CSV
with open('data.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
print(row)
4.6 使用configparser处理配置文件
import configparser
config = configparser.ConfigParser()
config['DEFAULT'] = {
'ServerAliveInterval': '45',
'Compression': 'yes',
'CompressionLevel': '9'
}
# 写入配置文件
with open('example.ini', 'w') as f:
config.write(f)
# 读取配置文件
config.read('example.ini')
print(config['DEFAULT']['ServerAliveInterval'])
第五章:标准输入输出流
5.1 sys.stdin、sys.stdout、sys.stderr
Python提供了三个标准流对象,分别对应输入、输出和错误输出:
import sys
# 写入标准错误
sys.stderr.write("这是一个错误消息\n")
# 从标准输入读取
for line in sys.stdin: # 按Ctrl+D(Unix)或Ctrl+Z(Windows)结束输入
print(f"你输入了: {line.strip()}")
# 重定向标准输出
original_stdout = sys.stdout
with open('output.txt', 'w') as f:
sys.stdout = f
print("这句话会写入文件而不是控制台")
sys.stdout = original_stdout
print("这句话会出现在控制台")
5.2 日志记录
在实际项目中,通常会使用logging模块代替print()进行日志记录:
import logging
# 配置日志
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='app.log',
filemode='w'
)
# 记录不同级别的日志
logging.debug("这是一个调试信息")
logging.info("程序运行正常")
logging.warning("这是一个警告")
logging.error("发生错误")
logging.critical("严重错误")
第六章:编码与国际化
6.1 字符编码
Python 3默认使用UTF-8编码,但在处理不同来源的文本时需要注意编码问题:
# 明确指定编码
with open('example.txt', 'w', encoding='utf-8') as f:
f.write("你好,世界!")
with open('example.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content)
# 处理不同编码
with open('gbk_file.txt', 'r', encoding='gbk') as f:
content = f.read()
# 编码转换
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)
6.2 处理编码错误
# 忽略编码错误
with open('file.txt', 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
# 替换无法编码的字符
with open('file.txt', 'r', encoding='utf-8', errors='replace') as f:
content = f.read()
# 使用'backslashreplace'保留原始字节
with open('file.txt', 'r', encoding='utf-8', errors='backslashreplace') as f:
content = f.read()
第七章:性能优化与最佳实践
7.1 性能优化技巧
# 1. 使用join()而不是多次print()
names = ['Alice', 'Bob', 'Charlie']
print(', '.join(names)) # 高效
# 不推荐:for name in names: print(name, end=', ')
# 2. 文件追加模式使用
with open('log.txt', 'a') as f:
f.write(f"{datetime.now()}: 事件发生\n")
# 3. 使用缓冲区
with open('large_output.txt', 'w', buffering=1024*1024) as f: # 1MB缓冲区
for i in range(1000000):
f.write(f"第{i}行\n")
7.2 最佳实践总结
- 总是明确指定文件编码(推荐UTF-8)
- 使用
with语句处理文件,确保文件正确关闭 - 处理文件时考虑异常情况(如文件不存在)
- 大文件使用逐行读取或分块读取,避免内存问题
- 敏感数据避免使用pickle,考虑更安全的序列化方式如json
- 输入数据务必进行类型转换和验证
- 合理使用格式化输出,提高代码可读性
- 使用日志记录代替print()进行调试
第八章:综合示例
8.1 用户数据管理系统
import json
import sys
def load_users(filename='users.json'):
"""从JSON文件加载用户数据"""
try:
with open(filename, 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
return {}
except json.JSONDecodeError:
print("错误: 用户数据文件损坏")
return {}
def save_users(users, filename='users.json'):
"""保存用户数据到JSON文件"""
with open(filename, 'w', encoding='utf-8') as f:
json.dump(users, f, indent=4, ensure_ascii=False)
def add_user(users):
"""添加新用户"""
username = input("请输入用户名: ").strip()
if username in users:
print(f"错误: 用户 '{username}' 已存在")
return
age = int(input("请输入年龄: "))
email = input("请输入邮箱: ").strip()
users[username] = {
'age': age,
'email': email,
'scores': []
}
print(f"用户 '{username}' 添加成功")
save_users(users)
def add_score(users):
"""为用户添加成绩"""
username = input("请输入用户名: ").strip()
if username not in users:
print(f"错误: 用户 '{username}' 不存在")
return
try:
score = float(input("请输入成绩(0-100): "))
if 0 <= score <= 100:
users[username]['scores'].append(score)
save_users(users)
print(f"成绩 {score} 已添加到用户 '{username}'")
else:
print("错误: 成绩必须在0-100之间")
except ValueError:
print("错误: 请输入有效的数字")
def show_statistics(users):
"""显示用户统计信息"""
if not users:
print("暂无用户数据")
return
print(f"\n{'用户名':<10}{'年龄':<5}{'成绩数':<8}{'平均分':<8}")
print("-" * 35)
for username, info in users.items():
scores = info['scores']
avg_score = sum(scores) / len(scores) if scores else 0
print(f"{username:<10}{info['age']:<5}{len(scores):<8}{avg_score:<8.2f}")
def main():
users = load_users()
while True:
print("\n" + "=" * 30)
print("用户数据管理系统")
print("=" * 30)
print("1. 添加用户")
print("2. 添加成绩")
print("3. 显示统计")
print("4. 退出")
print("=" * 30)
choice = input("请选择操作(1-4): ").strip()
if choice == '1':
add_user(users)
elif choice == '2':
add_score(users)
elif choice == '3':
show_statistics(users)
elif choice == '4':
print("感谢使用,再见!")
sys.exit(0)
else:
print("无效选择,请重新输入")
if __name__ == "__main__":
main()
8.2 日志文件分析器
import re
from collections import Counter
def analyze_log_file(logfile, encoding='utf-8'):
"""分析日志文件,统计错误类型和频率"""
error_patterns = {
'ERROR': r'ERROR',
'WARNING': r'WARNING',
'CRITICAL': r'CRITICAL',
'IP地址': r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
}
results = {key: Counter() for key in error_patterns}
total_lines = 0
try:
with open(logfile, 'r', encoding=encoding) as f:
for line in f:
total_lines += 1
for key, pattern in error_patterns.items():
matches = re.findall(pattern, line)
for match in matches:
results[key][match] += 1
except FileNotFoundError:
print(f"错误: 文件 '{logfile}' 不存在")
return None
except PermissionError:
print(f"错误: 没有权限读取文件 '{logfile}'")
return None
return {
'total_lines': total_lines,
'results': results
}
def print_analysis(analysis):
"""打印分析结果"""
if analysis is None:
return
print(f"\n日志文件分析结果")
print("=" * 50)
print(f"总行数: {analysis['total_lines']}")
print("-" * 50)
for key, counter in analysis['results'].items():
print(f"\n{key} 统计:")
if counter:
for item, count in counter.most_common(5):
print(f" {item}: {count}次")
else:
print(f" 无")
if __name__ == "__main__":
logfile = input("请输入日志文件路径: ").strip()
analysis = analyze_log_file(logfile)
print_analysis(analysis)
结语
Python 3的输入输出功能设计直观且灵活,涵盖了从控制台交互到文件处理的多种场景。通过熟练掌握这些工具,您可以轻松构建功能丰富、用户友好的Python程序。从简单的input()和print(),到复杂的文件操作、数据序列化,再到性能优化和最佳实践,本文全面覆盖了Python 3 I/O系统的各个方面。
12万+

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



