☰
Python 命令行参数:从 sys.argv 到 argparse
2026/10/3 7:26:16 网站建设 项目流程

命令行参数,指的是程序启动时、在命令里一起传给它的那串字符串:

python 脚本.py 你好 123

这里的脚本.py、你好、123,就是命令行参数。

它解决的核心问题只有一个:让程序在"无人值守"的情况下拿到外部数据。

  • 不用改代码(对比"把数据写死在代码里")
  • 不用人盯着(对比input())

1. 参数从哪来:shell 与 PATH

命令不是"python 直接看到"的,中间有个中间人——shell(命令解释器),就是 PyCharm 里的"终端"。它做两步:

  1. 通过环境变量PATH找到python这个程序(python3.6/python3.12);
  2. 把命令里剩下的内容原封不动丢给python。
你敲的: python 脚本.py 你好 123 │ └────────┴──────┘ │ ↓ shell 通过 PATH 这几个"词" 找到这个程序 原封不动塞给 python

关键:对 shell 来说,脚本.py、你好、123只是一串字符串。这串被丢给 python 的字符串,就是命令行参数。所以"命令行参数"里的参数,是传给 python 解释器的参数。

2. 从 sys.argv 到 argparse

sys.argv:能用,但别这么写

Python 用标准库sys里的sys.argv接收参数,它是一个列表:

import sys print(sys.argv)
$ python test.py 你好 123 ['test.py', '你好', '123']

两个要注意的点:

  • sys.argv[0]是脚本名本身,真正的参数从sys.argv[1]开始。
  • 列表里全是字符串,'123'不是数字。

所以想做运算必须手动转换:

import sys result = int(sys.argv[1]) + 1 # 不转就 TypeError

更阴险的坑:'123' + '1'不会报错,而是拼接成'1231'。这种不报错的错误最难查。

一旦参数变多、变复杂,sys.argv的三个死穴就暴露了:

死穴表现
位置靠记第几个参数是什么,全靠记忆;传多传少要自己写if判断
类型手动每个参数都得手动int(),还得记住哪个该转
没有说明书用户不知道有哪些参数、什么顺序、哪些必填;敲错也没有友好提示

argparse:直接用这个

参数一复杂,就别再用sys.argv裸写了,直接用标准库argparse:

import argparse parser = argparse.ArgumentParser(description="备份脚本") parser.add_argument('--src', required=True, help='源目录') parser.add_argument('--dst', required=True, help='目标目录') parser.add_argument('--days', type=int, default=7, help='保留天数') parser.add_argument('--verbose', action='store_true', help='打印详细日志') args = parser.parse_args() print(args.src, args.dst, args.days, args.verbose)

它一次解决了sys.argv的所有痛点:

能力写法作用
名字--src用args.src取值,不用记位置
类型type=int自动做int()转换
默认值default=7用户不传就用默认值
开关action='store_true'敲了是True,不敲是False
帮助help='...'自动生成-h帮助信息
校验required=True缺参数或类型不对,自动报错

3. 两类参数:位置参数 vs 可选参数

argparse里的参数分两类,看add_argument的第一个参数带不带--就能区分:

不带--(位置参数)带--(可选参数)
怎么识别靠位置(第几个)靠名字(--days)
能不能不传通常必须传可以不传(有默认值)
顺序不能乱随便
适合装什么程序最核心、不给就没法干活的输入配置项、开关这类次要信息
parser.add_argument('filename') # 不带 -- → 位置参数(必填) parser.add_argument('--days', type=int, default=7) # 带 -- → 可选参数(有默认值) parser.add_argument('--verbose', action='store_true') # 带 -- → 可选参数(开关)
$ python test.py 报告.txt → 报告.txt 7 False $ python test.py 报告.txt --days 30 → 报告.txt 30 False $ python test.py → 报错:the following arguments are required: filename

4. 延伸

单横杠 vs 双横杠

写法叫法特点
-h短选项一个横杠 + 通常一个字母,打字快
--help长选项两个横杠 + 一个单词,看得懂

它们常常是同一个参数的两种写法,一次就能把两个名字绑给同一个参数:

parser.add_argument('-v', '--verbose', action='store_true')

于是下面三种敲法效果完全一样:

python test.py -v python test.py --verbose python test.py -v --verbose

注意:判断"位置参数 vs 可选参数"看的是有没有横杠,不是有几个横杠。-v和--verbose都是可选参数。另外,短选项可以合并:-abc等价于-a -b -c。

不是 Python 独有的:git / docker 同理

命令行参数是所有命令行程序共用的通用约定(来自 Unix / POSIX)。git是 C 写的、docker是 Go 写的,但命令行长相一样:

git commit -m "修复登录bug" │ │ │ │ │ │ │ └── 可选参数 -m 的值 │ │ └── 可选参数(短选项) │ └── 位置参数(子命令) └── 程序名

语言不同,约定相同——每个语言只是各有一个解析这套参数的工具:Python 用argparse,Go 用flag/cobra,C 用getopt。学会一套,就能拆解任何命令行程序。

怎么快速读一份-h帮助

先记符号:

符号含义
[]可选
()分组(通常配合|,表示这组里必须选一个)
|或者
大写单词(QUERY)占位符,要填真实的值,别照抄这个词

读法三步:

  1. 读usage行,找出必填的(没有方括号的、圆括号里的);
  2. 看参数列表,判断每个参数要不要给值——名字后面跟大写占位符就要值,光秃秃一个名字就是开关;
  3. 拼命令:必填先凑齐,可选按需加。

保命技巧:拿不准就只给必填先跑一次。argparse 的报错会直接告诉你缺了哪个参数、哪个值不合法——报错信息本身就是第二份 help。

互斥组(a | b | c)从哪来

帮助里那种(--http | --service | --mock MOCK),圆括号和竖线不是手写的,是用add_mutually_exclusive_group()定义后自动渲染的:

group = parser.add_mutually_exclusive_group(required=True) group.add_argument('--http', action='store_true') group.add_argument('--service', action='store_true') group.add_argument('--mock')

关键差别:普通参数挂在parser上,互斥参数挂在group上。required=True时 usage 显示(a | b | c)(必选其一);改成False就变成[a | b | c](可选,但选了也只能选一个)。

5. 总结

一条问题链

问题① 怎么让程序"无人值守"地拿到外部数据? └─► 方案:命令行参数 └─► 新问题② 参数怎么交到脚本手里? └─► 方案:sys.argv(列表 / 全是字符串) └─► 新问题③ 类型要手动转、位置靠记、没说明书 └─► 方案:argparse └─► 新概念④ 两类参数:位置参数 / 可选参数

速查表

需求sys.argvargparse
取参数sys.argv[1](靠位置)args.src(靠名字)
类型转换手动int()type=int自动
默认值自己写ifdefault=7
开关'--verbose' in sys.argvaction='store_true'
帮助信息无自动-h
参数校验无,容易IndexError自动报错

命令行参数不是 Python 独有的 API,而是一套看懂任何命令行程序的通用能力:程序名 → 位置参数(子命令)→ 可选参数(-x/--xxx)→ 参数的值。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询