Python 命令行参数入门:让脚本“听懂”用户指令
在日常开发中,我们经常需要运行一个 Python 脚本,并根据不同的需求传递不同的配置信息。比如,你想运行一个日志分析工具,但希望它只处理某一天的数据,或者指定输出文件的路径。手动修改代码显然不够灵活,这时就需要用到 Python 命令行参数。
你可以把命令行参数想象成一个“遥控器”——脚本是电视,而用户通过命令行输入的参数就是遥控器上的按钮。按下不同的按钮,电视就会执行不同的操作,比如切换频道、调节音量、打开字幕。Python 通过解析这些“按钮”(参数),让程序具备了动态响应的能力。
接下来,我们从最基础的 sys.argv 开始,逐步深入到更专业的 argparse 模块,带你掌握这一实用技能。
使用 sys.argv 获取原始参数
Python 内置的 sys 模块提供了一个名为 argv 的列表,它包含了运行脚本时传递的所有参数。这是最原始、最直接的方式。
import sys
print("脚本名称:", sys.argv[0])
for i, arg in enumerate(sys.argv[1:], start=1):
print(f"第 {i} 个参数: {arg}")
运行示例:
python hello_argv.py 你好 世界 --verbose
输出结果:
脚本名称: hello_argv.py
第 1 个参数: 你好
第 2 个参数: 世界
第 3 个参数: --verbose
💡 小贴士:
sys.argv[0]始终是脚本文件名,所以真正的参数从索引1开始。这个机制就像你按下遥控器的“电源键”时,设备自动记录了“你按了哪个键”。
虽然 sys.argv 简单易用,但它的问题也很明显:你需要手动判断参数的含义,无法验证类型,也不支持长参数名(如 --help)。因此,对于复杂脚本,我们推荐使用 argparse。
argparse:现代 Python 命令行解析利器
argparse 是 Python 标准库中专为命令行参数设计的模块,功能强大,支持长参数、短参数、默认值、类型校验,甚至自动生成帮助信息。
创建基本参数解析器
import argparse
parser = argparse.ArgumentParser(description="一个简单的问候程序")
parser.add_argument("name", help="要问候的人的名字")
parser.add_argument("--greeting", default="你好", help="自定义问候语,默认为‘你好’")
args = parser.parse_args()
print(f"{args.greeting}, {args.name}!")
运行示例:
python greet.py 张三
python greet.py 李四 --greeting=哈喽
✅ 关键点:
add_argument()方法用于定义参数。name是位置参数,必须提供;--greeting是可选参数,可以省略,有默认值。
支持类型验证和默认值
argparse 可以自动校验参数类型,避免程序因错误输入崩溃。
import argparse
parser = argparse.ArgumentParser(description="一个简单的加法计算器")
parser.add_argument("a", type=int, help="第一个数字")
parser.add_argument("b", type=int, help="第二个数字")
parser.add_argument("--verbose", action="store_true", help="启用详细输出")
args = parser.parse_args()
result = args.a + args.b
if args.verbose:
print(f"{args.a} + {args.b} = {result}")
else:
print(result)
运行示例:
python calculator.py 5 3 --verbose
python calculator.py 10 20
🔍 注意:
action="store_true"表示当用户输入--verbose时,args.verbose为True,否则为False。这类似于“开关按钮”——按了就开,不按就关。
高级用法:参数分组与子命令
当脚本功能越来越多时,我们可以将参数分组,或使用子命令来组织逻辑。
使用 add_argument_group 分组
import argparse
parser = argparse.ArgumentParser(description="配置管理工具")
db_group = parser.add_argument_group("数据库配置")
db_group.add_argument("--db-host", default="localhost", help="数据库主机")
db_group.add_argument("--db-port", type=int, default=5432, help="数据库端口")
file_group = parser.add_argument_group("文件路径")
file_group.add_argument("--input", required=True, help="输入文件路径")
file_group.add_argument("--output", help="输出文件路径")
args = parser.parse_args()
print(f"数据库: {args.db_host}:{args.db_port}")
print(f"输入: {args.input}")
print(f"输出: {args.output}")
运行示例:
python config_manager.py --input data.txt --output result.json --db-port 3306
输出:
数据库: localhost:3306
输入: data.txt
输出: result.json
📌 优势:分组让命令行参数更清晰,尤其适合配置类工具。
使用 subparsers 实现子命令
子命令类似于 Git 的 git add、git commit,让脚本支持多种操作。
import argparse
parser = argparse.ArgumentParser(description="一个多功能命令行工具")
subparsers = parser.add_subparsers(dest="command", help="可用命令")
add_parser = subparsers.add_parser("add", help="添加两个数字")
add_parser.add_argument("a", type=int)
add_parser.add_argument("b", type=int)
mul_parser = subparsers.add_parser("multiply", help="相乘两个数字")
mul_parser.add_argument("a", type=int)
mul_parser.add_argument("b", type=int)
args = parser.parse_args()
if args.command == "add":
print(f"和为: {args.a + args.b}")
elif args.command == "multiply":
print(f"积为: {args.a * args.b}")
运行示例:
python cli_tool.py add 5 3
python cli_tool.py multiply 4 6
🌟 比喻:子命令就像一个多功能遥控器,每个按钮对应一个功能。按下“add”按钮,执行加法;按下“multiply”按钮,执行乘法。
常见问题与最佳实践
| 问题 | 建议解决方案 |
|---|---|
| 参数名过长或混乱 | 使用短参数(如 -v)和长参数(如 --verbose)结合 |
| 用户忘记输入必要参数 | 使用 required=True 强制要求 |
| 参数类型错误(如输入字符串给整数) | 使用 type=int 或 type=float 自动校验 |
| 帮助信息不清晰 | 为每个参数添加 help 描述 |
| 多个子命令逻辑复杂 | 使用 add_subparsers 拆分逻辑 |
实际案例:日志分析脚本
我们来实现一个真实的场景:一个日志分析工具,支持过滤级别、指定文件、输出到文件。
import argparse
import re
parser = argparse.ArgumentParser(description="日志分析工具")
parser.add_argument("file", help="日志文件路径")
parser.add_argument("--level", choices=["INFO", "WARN", "ERROR"], help="过滤日志级别")
parser.add_argument("--output", help="输出文件路径")
parser.add_argument("--count", action="store_true", help="只统计条数")
args = parser.parse_args()
try:
with open(args.file, "r", encoding="utf-8") as f:
lines = f.readlines()
except FileNotFoundError:
print(f"错误:文件 {args.file} 不存在。")
exit(1)
filtered_lines = []
for line in lines:
if args.level and args.level not in line:
continue
filtered_lines.append(line)
if args.count:
print(f"符合条件的日志条数: {len(filtered_lines)}")
else:
output = args.output or "output.txt"
with open(output, "w", encoding="utf-8") as f:
f.writelines(filtered_lines)
print(f"已将 {len(filtered_lines)} 条日志写入 {output}")
运行示例:
python log_analyzer.py app.log --level=WARN --output warn.log
✅ 这个脚本可直接用于生产环境,具备错误处理、类型校验、参数过滤等完整功能。
总结:让脚本真正“听懂”用户
掌握 Python 命令行参数,意味着你的脚本不再是一个“死程序”,而是一个“活工具”。它可以接收用户输入,动态调整行为,大大提升可复用性和用户体验。
从 sys.argv 的原始方式,到 argparse 的强大功能,再到子命令和分组的高级组织,每一步都在让你的脚本更专业、更易用。
记住:一个优秀的命令行工具,不只是“能跑”,更要“好用”。当你写出一个能被人轻松调用的脚本时,你就真正掌握了 Python 的精髓。
别再让脚本只能硬编码了。从今天起,给它一个“耳朵”——让它听懂你的指令。