📚 目录
- [sys 模块是什么](#sys 模块是什么)
- [命令行参数 sys.argv](#命令行参数 sys.argv)
- [模块搜索路径 sys.path](#模块搜索路径 sys.path)
- [程序退出 sys.exit ()](#程序退出 sys.exit ())
- 标准输入输出流
- 版本与平台检测
- 内存与递归控制
- 异常处理
- 完整实战案例
- 常见问题与避坑
- 速查表
- 总结
一、sys 模块是什么
sys 是 Python 标准库中最核心的模块,全称 "System-specific"。它提供了与 Python 解释器直接交互的接口。
1.1 为什么需要它?
表格
| 场景 | 解决方案 |
|---|---|
| 脚本启动时传参数 | sys.argv |
| 控制模块导入路径 | sys.path |
| 程序退出返回状态码 | sys.exit() |
| 输出重定向到文件 | sys.stdout |
| 判断操作系统 | sys.platform |
1.2 快速上手
python
运行
import sys
# 查看所有功能
print(dir(sys))
# 查看Python版本
print(sys.version)
二、命令行参数 sys.argv
sys.argv 是一个列表,存储命令行执行脚本时传入的所有参数。
2.1 基本用法
python
运行
# script.py
import sys
print(sys.argv)
运行效果:
bash
运行
python script.py hello 123 --name
# 输出: ['script.py', 'hello', '123', '--name']
2.2 参数解析
表格
| 索引 | 含义 |
|---|---|
sys.argv[0] |
脚本文件名 |
sys.argv[1] |
第一个参数 |
sys.argv[2:] |
剩余所有参数 |
2.3 实用示例
python
运行
import sys
# 获取参数(带默认值)
if len(sys.argv) < 2:
name = "游客"
else:
name = sys.argv[1]
print(f"你好, {name}!")
# 数字参数需要转换
if len(sys.argv) > 2:
try:
age = int(sys.argv[2])
print(f"年龄: {age}")
except ValueError:
print("年龄必须是数字")
2.4 简单命令行工具
python
运行
import sys
args = sys.argv[1:]
if not args:
print("用法: python tool.py [--help] [--version]")
sys.exit(1)
for arg in args:
if arg == "--help":
print("这是一个示例工具")
elif arg == "--version":
print("版本 1.0")
else:
print(f"未知参数: {arg}")
三、模块搜索路径 sys.path
sys.path 是一个列表,存储 Python 查找模块的所有路径。
3.1 查看所有路径
python
运行
import sys
# 遍历打印所有模块搜索路径
for path in sys.path:
print(path)
3.2 路径顺序
Python 按 sys.path 的顺序查找模块,找到第一个就停止:
- 当前脚本所在目录
- 环境变量
PYTHONPATH配置的路径 - 系统默认安装目录
3.3 添加自定义路径
python
运行
import sys
# 添加到末尾(低优先级)
sys.path.append('/my/modules')
# 添加到开头(最高优先级)
sys.path.insert(0, '/priority/modules')
3.4 临时添加路径(推荐)
python
运行
import sys
import contextlib
@contextlib.contextmanager
def add_to_path(path):
"""临时添加路径,用完自动移除"""
try:
sys.path.insert(0, path)
yield
finally:
sys.path.remove(path)
# 使用方式
with add_to_path('/tmp/my_lib'):
import my_module # 从临时路径导入
3.5 查看已加载模块
python
运行
import sys
# 查看所有已导入的模块
print(sys.modules.keys())
# 检查模块是否已加载
if 'requests' in sys.modules:
print("requests 已加载")
四、程序退出 sys.exit ()
用于主动终止 Python 程序,支持返回状态码和退出提示。
4.1 基本用法
python
运行
import sys
# 正常退出(状态码 0)
sys.exit()
sys.exit(0)
# 错误退出(状态码 1)
sys.exit(1)
# 带信息退出
sys.exit("程序出错了")
4.2 状态码约定
表格
| 状态码 | 含义 |
|---|---|
| 0 | 程序执行成功 |
| 1 | 一般业务错误 |
| 2 | 命令行参数错误 |
| 130 | 用户手动中断(Ctrl+C) |
4.3 实战示例
python
运行
import sys
def process_file(filename):
"""处理文件,失败时退出"""
try:
with open(filename, 'r') as f:
return f.read()
except FileNotFoundError:
sys.exit(f"错误: 文件 '{filename}' 不存在")
except PermissionError:
sys.exit(f"错误: 没有权限读取 '{filename}'")
except Exception as e:
sys.exit(f"错误: {e}")
# 主程序
if __name__ == "__main__":
if len(sys.argv) < 2:
sys.exit("用法: python script.py <文件名>")
content = process_file(sys.argv[1])
print(f"文件内容长度: {len(content)}")
4.4 终端查看退出状态码
bash
运行
# Linux/Mac
python script.py
echo $?
# Windows
python script.py
echo %ERRORLEVEL%
五、标准输入输出流
Python 三大标准流,负责程序的输入、输出、错误打印。
5.1 三大标准流
表格
| 对象 | 用途 | 默认目标 |
|---|---|---|
sys.stdin |
标准输入 | 键盘 |
sys.stdout |
标准输出 | 屏幕 |
sys.stderr |
标准错误 | 屏幕 |
5.2 sys.stdin - 读取输入
python
运行
import sys
# 读取一行
line = sys.stdin.readline()
print(f"读取: {line}")
# 读取所有行
for line in sys.stdin:
print(f"行: {line.strip()}")
# 读取指定字符数
data = sys.stdin.read(100)
管道输入检测:
python
运行
import sys
# 判断是否有管道输入
if not sys.stdin.isatty():
data = sys.stdin.read()
print(f"从管道读取 {len(data)} 字符")
else:
print("没有管道输入,等待用户输入...")
user_input = input("请输入: ")
5.3 sys.stdout - 输出控制
python
运行
import sys
# 直接写入(不自动换行)
sys.stdout.write("Hello\n")
# 重定向输出到文件
original = sys.stdout
with open('output.txt', 'w') as f:
sys.stdout = f
print("这段内容进入文件")
sys.stdout = original # 恢复默认输出
print("回到屏幕输出")
5.4 sys.stderr - 错误输出
python
运行
import sys
# 错误信息独立输出
sys.stderr.write("警告: 配置缺失\n")
# 重定向错误到日志文件
sys.stderr = open('error.log', 'w')
print("错误信息", file=sys.stderr)
5.5 同时输出到屏幕和文件
python
运行
import sys
class Tee:
"""同时输出到多个目标"""
def __init__(self, *files):
self.files = files
def write(self, obj):
for f in self.files:
f.write(obj)
def flush(self):
for f in self.files:
f.flush()
# 同时输出到屏幕和日志文件
log_file = open('app.log', 'w')
sys.stdout = Tee(sys.stdout, log_file)
print("这条信息同时出现在屏幕和日志文件")
六、版本与平台检测
用于判断 Python 版本、操作系统,实现跨平台兼容。
6.1 Python 版本信息
python
运行
import sys
# 完整版本字符串
print(sys.version)
# 版本元组(便于比较)
print(sys.version_info)
# 单独获取版本号
print(f"主版本: {sys.version_info.major}")
print(f"次版本: {sys.version_info.minor}")
print(f"微版本: {sys.version_info.micro}")
6.2 版本兼容性检查
python
运行
import sys
# 检查 Python 版本
if sys.version_info < (3, 8):
print("此脚本需要 Python 3.8+")
sys.exit(1)
# 根据版本使用不同特性
if sys.version_info >= (3, 9):
# Python 3.9+ 新特性
pass
else:
# 兼容旧版本
pass
6.3 操作系统检测
python
运行
import sys
platform = sys.platform
if platform == 'win32':
print("Windows 系统")
elif platform == 'linux':
print("Linux 系统")
elif platform == 'darwin':
print("macOS 系统")
6.4 其他系统信息
python
运行
import sys
# 最大整数
print(f"最大整数: {sys.maxsize}")
# 字节序
print(f"字节序: {'小端' if sys.byteorder == 'little' else '大端'}")
# 解释器路径
print(f"Python 解释器路径: {sys.executable}")
七、内存与递归控制
7.1 获取对象大小
python
运行
import sys
# 基本类型占用字节数
print(f"整数: {sys.getsizeof(42)} 字节")
print(f"字符串: {sys.getsizeof('hello')} 字节")
print(f"列表: {sys.getsizeof([1,2,3])} 字节")
# 空对象大小
print(f"空列表: {sys.getsizeof([])} 字节")
print(f"空字典: {sys.getsizeof({})} 字节")
7.2 递归深度控制
python
运行
import sys
# 查看当前递归限制
print(f"递归限制: {sys.getrecursionlimit()}")
# 设置新限制(谨慎使用!)
sys.setrecursionlimit(10000)
7.3 引用计数
python
运行
import sys
a = [1, 2, 3]
b = a
c = a
# 查看引用次数(getrefcount 本身会增加一次计数)
print(f"引用计数: {sys.getrefcount(a)}") # 输出 4
del b
print(f"删除后: {sys.getrefcount(a)}") # 输出 3
八、异常处理
8.1 获取异常信息
python
运行
import sys
try:
1 / 0
except ZeroDivisionError:
exc_type, exc_value, exc_tb = sys.exc_info()
print(f"异常类型: {exc_type.__name__}")
print(f"异常信息: {exc_value}")
print(f"追踪信息: {exc_tb}")
8.2 自定义异常钩子
python
运行
import sys
def custom_excepthook(exc_type, exc_value, exc_tb):
"""自定义全局异常处理"""
print("=" * 40)
print("程序出错了!")
print(f"类型: {exc_type.__name__}")
print(f"信息: {exc_value}")
print("=" * 40)
# 设置自定义异常处理
sys.excepthook = custom_excepthook
# 测试未捕获异常
# raise ValueError("测试错误")
九、完整实战案例
案例 1:文件批量处理工具
python
运行
#!/usr/bin/env python3
# file_batch.py - 批量文件处理工具
import sys
import os
class FileBatch:
"""批量文件处理器"""
def __init__(self):
self.verbose = False
self.output_dir = "output"
def parse_args(self):
"""解析命令行参数"""
args = sys.argv[1:]
for i, arg in enumerate(args):
if arg in ("-v", "--verbose"):
self.verbose = True
elif arg in ("-o", "--output"):
if i + 1 < len(args):
self.output_dir = args[i + 1]
elif arg in ("-h", "--help"):
self.show_help()
sys.exit(0)
elif not arg.startswith("-"):
return arg
return None
def show_help(self):
"""显示帮助信息"""
print("""
批量文件处理工具 v1.0
用法: python file_batch.py [选项] <输入>
选项:
-v, --verbose 显示详细信息
-o, --output DIR 输出目录 (默认: output)
-h, --help 显示帮助
示例:
python file_batch.py data.txt
python file_batch.py -v -o results data.txt
""")
def process_file(self, filepath):
"""处理单个文件"""
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
lines = len(content.split('\n'))
os.makedirs(self.output_dir, exist_ok=True)
basename = os.path.basename(filepath)
output_path = os.path.join(self.output_dir, f"processed_{basename}")
with open(output_path, 'w', encoding='utf-8') as f:
f.write(f"原文件: {filepath}\n")
f.write(f"行数: {lines}\n")
f.write(f"字符数: {len(content)}\n")
return lines
except FileNotFoundError:
sys.stderr.write(f"错误: 文件不存在 - {filepath}\n")
return None
except PermissionError:
sys.stderr.write(f"错误: 权限不足 - {filepath}\n")
return None
except Exception as e:
sys.stderr.write(f"错误: {e}\n")
return None
def run(self):
"""主运行方法"""
try:
input_path = self.parse_args()
if not input_path:
sys.stderr.write("错误: 请指定输入文件\n")
self.show_help()
sys.exit(1)
if self.verbose:
sys.stderr.write(f"[详细] 输入: {input_path}\n")
sys.stderr.write(f"[详细] 输出目录: {self.output_dir}\n")
if os.path.isfile(input_path):
result = self.process_file(input_path)
if result is not None:
print(f"处理完成: {input_path} -> {result} 行")
else:
sys.stderr.write(f"错误: 无效输入 - {input_path}\n")
sys.exit(1)
except KeyboardInterrupt:
sys.stderr.write("\n用户中断\n")
sys.exit(130)
except Exception as e:
sys.stderr.write(f"未处理异常: {e}\n")
sys.exit(1)
if __name__ == "__main__":
app = FileBatch()
app.run()
案例 2:管道数据处理
python
运行
#!/usr/bin/env python3
# pipe_processor.py - 管道数据处理
import sys
import json
def process_line(line):
"""处理单行数据"""
line = line.strip()
if not line:
return None
return {
"original": line,
"length": len(line),
"words": len(line.split())
}
def main():
results = []
if sys.stdin.isatty():
print("请输入数据(Ctrl+D 结束):")
lines = sys.stdin.readlines()
else:
lines = sys.stdin.readlines()
for line in lines:
result = process_line(line)
if result:
results.append(result)
if results:
print(json.dumps(results, ensure_ascii=False, indent=2))
sys.stderr.write(f"处理完成: {len(results)} 条记录\n")
else:
sys.stderr.write("警告: 没有有效数据\n")
sys.exit(1)
if __name__ == "__main__":
main()
案例 3:环境检测工具
python
运行
#!/usr/bin/env python3
# env_check.py - 环境检测工具
import sys
def check_environment():
"""检查运行环境"""
checks = []
py_ok = sys.version_info >= (3, 7)
checks.append(("Python >= 3.7", py_ok))
platform_ok = sys.platform in ['linux', 'darwin', 'win32']
checks.append(("平台支持", platform_ok))
print("=" * 40)
print("环境检测报告")
print("=" * 40)
print(f"Python版本: {sys.version_info.major}.{sys.version_info.minor}")
print(f"平台: {sys.platform}")
print(f"解释器路径: {sys.executable}")
print("\n检测项:")
all_ok = True
for name, ok in checks:
status = "✓" if ok else "✗"
print(f" [{status}] {name}")
if not ok:
all_ok = False
print("=" * 40)
if all_ok:
print("环境检查通过")
return 0
else:
print("环境检查失败")
return 1
if __name__ == "__main__":
sys.exit(check_environment())
十、常见问题与避坑
10.1 五大常见坑点
表格
| 坑点 | 说明 | 解决方案 |
|---|---|---|
| argv 类型问题 | 所有参数都是字符串 | 数字必须用 int()/float() 转换 |
| path 修改不持久 | 仅当前进程生效 | 设置环境变量 PYTHONPATH |
| 重定向忘记恢复 | 输出丢失 / 异常 | 先保存原始对象,用完立即恢复 |
| 多线程输出混乱 | 打印内容交错 | 使用 logging 模块 |
| 递归过深 | 栈溢出崩溃 | 优先用迭代替代深度递归 |
10.2 最佳实践
python
运行
import sys
# 安全获取命令行参数
def safe_get_arg(index, default=None):
return sys.argv[index] if len(sys.argv) > index else default
# 上下文管理器管理输出重定向
class Redirect:
def __init__(self, target):
self.target = target
self.original = sys.stdout
def __enter__(self):
sys.stdout = self.target
return self
def __exit__(self, *args):
sys.stdout = self.original
# 使用示例
with open('out.txt', 'w') as f:
with Redirect(f):
print("这段内容写入文件")
print("恢复屏幕输出")
十一、速查表
11.1 常用属性速查
表格
| 属性 | 用途 | 示例 |
|---|---|---|
sys.argv |
命令行参数 | args = sys.argv[1:] |
sys.path |
模块搜索路径 | sys.path.append('./lib') |
sys.version |
Python 版本 | print(sys.version) |
sys.platform |
操作系统 | if sys.platform == 'win32' |
sys.maxsize |
最大整数 | max_val = sys.maxsize |
11.2 常用方法速查
表格
| 方法 | 用途 | 示例 |
|---|---|---|
sys.exit() |
退出程序 | sys.exit(1) |
sys.getsizeof() |
获取对象大小 | size = sys.getsizeof(obj) |
sys.getrecursionlimit() |
获取递归限制 | limit = sys.getrecursionlimit() |
sys.exc_info() |
获取异常信息 | type, value, tb = sys.exc_info() |
11.3 标准流速查
表格
| 对象 | 常用操作 | 示例 |
|---|---|---|
sys.stdin |
读取输入 | data = sys.stdin.read() |
sys.stdout |
标准输出 | sys.stdout.write('text') |
sys.stderr |
错误输出 | sys.stderr.write('error') |
十二、总结
核心要点
sys 模块是 Python 最基础的系统交互接口,掌握它能让你的脚本:
- ✅ 更灵活:通过命令行参数控制行为
- ✅ 更专业:使用标准退出状态码
- ✅ 更健壮:完善的错误处理和环境检测
- ✅ 更实用:支持管道数据处理、输出重定向
学习路径
- 入门 :掌握
argv、exit()、stdout - 进阶 :学会
path管理、环境检测 - 精通:异常钩子、内存分析、自定义重定向
一句话总结
sys = 脚本与 Python 解释器的桥梁,是每个 Python 程序员的必修课