Python 命令行参数解析教程

1. 基础入门:sys.argv 快速获取

写命令行工具时,最先想到的往往是能不能直接拿到用户敲的参数?Python 标准库的 sys.argv 就能解决这个问题——它是一个纯字符串列表,第一个永远是脚本的名称(比如script.py),后面依次跟所有空格分隔的输入。

import sys

print("接收到的完整命令行参数列表:", sys.argv)

假设你保存为 basic_argv.py,然后在终端执行:

python basic_argv.py hello world 123

输出就是:

接收到的完整命令行参数列表: ['basic_argv.py', 'hello', 'world', '123']

不过这种方式有个硬伤:没有任何类型检查、约束逻辑、帮助文档——工具复杂一点,用户和你自己都会疯掉。


2. 核心工具:argparse 标准库

对于稍微正式一点的命令行工具,Python 内置的 argparse 绝对是首选:无需额外安装、功能覆盖 90% 以上的场景、自动生成漂亮的 -h/--help 文档。

2.1 三步搭建框架

创建 argparse 解析流程很简单,分三步走:

  1. 新建 ArgumentParser 对象(相当于搭个参数收纳箱)
  2. add_argument() 往箱子里塞各种参数规则
  3. 调用 parse_args() 完成解析,返回一个带属性的对象
import argparse

# 第一步:搭收纳箱
parser = argparse.ArgumentParser(
    prog="my_cli_tool",          # 工具的正式名称(帮助文档用)
    description="这是一个示例工具的简介",  # 开头的说明
    epilog="© 202X 我的开发笔记"  # 帮助文档结尾的版权/补充信息
)

# 第二步:塞参数(后面会详细讲)
parser.add_argument("file_path", help="要操作的文件路径")

# 第三步:解析+用
if __name__ == "__main__":
    args = parser.parse_args()
    print(f"开始处理文件:{args.file_path}")

2.2 五种常用的参数类型

① 位置参数(必选,无短/长选项)

位置参数按用户输入的顺序绑定,适合逻辑上必须先填的核心内容(比如文件路径、操作名)。

parser.add_argument(
    "outfile", 
    help="数据库备份的输出文件路径"  # 必须加 help!!
)

② 可选参数(有短/长选项)

可选参数可以按任意顺序输入,适合开关、配置项等非核心内容。短选项一般是单字母(比如-u),长选项更易读(比如--user)。

parser.add_argument(
    "-u", "--user",           # 可以只写短/只写长,也可以都写
    required=True,            # 可选参数也可以强制要求填!
    help="登录数据库的用户名"
)

③ 带默认值的可选参数

减少用户的输入负担,默认值会在帮助文档的 (default: xxx) 里自动显示。

parser.add_argument(
    "--host",
    default="localhost",
    help="MySQL 主机地址"
)

④ 类型转换+验证

默认所有参数都是字符串,用 type 可以直接转成 int/float/bool 等,甚至可以自定义验证函数!

# 直接转 int
parser.add_argument(
    "--port",
    type=int,
    default=3306,
    help="MySQL 端口号"
)

# 自定义验证(比如要求端口在1-65535之间)
def check_port(port_str):
    port = int(port_str)
    if 1 <= port <= 65535:
        return port
    raise argparse.ArgumentTypeError(f"端口必须在 1-65535 之间,你输入的是 {port}")

parser.add_argument(
    "--safe-port",
    type=check_port,
    default=3306,
    help="安全的 MySQL 端口号"
)

⑤ 布尔开关参数

不需要跟值,只要出现就设为 True(或者反过来设为 False),用 action 参数控制。

# 出现 --gz 就设为 True
parser.add_argument(
    "-g", "--gz",
    action="store_true",
    help="是否启用 GZIP 压缩备份文件"
)

# 出现 --no-color 就设为 False(默认 True)
parser.add_argument(
    "--no-color",
    action="store_false",
    dest="enable_color",  # dest可以修改解析后对象的属性名
    default=True,
    help="是否禁用彩色输出"
)

⑥ 限定选择的参数

choices 限定输入只能是列表里的选项,帮助文档也会自动列出这些选项。

parser.add_argument(
    "--format",
    choices=["json", "xml", "csv"],
    default="json",
    help="备份文件的输出格式"
)

2.3 完整的实战示例:数据库备份工具

把上面的内容整合起来,写一个简单但能用的 MySQL 备份工具模板:

import argparse

def backup_database(outfile, host, port, user, password, database, gz):
    """模拟数据库备份的核心逻辑"""
    print(f"✅ 开始准备备份任务")
    print(f"📁 输出文件:{outfile}{'.gz' if gz else ''}")
    print(f"🔗 连接信息:{user}@{host}:{port}/{database}")
    if gz:
        print("📦 GZIP 压缩已启用")

if __name__ == "__main__":
    # 1. 搭收纳箱
    parser = argparse.ArgumentParser(
        prog="db_backup",
        description="轻量级 MySQL 数据库本地备份工具",
        epilog="⚠️ 使用前请确保已安装 mysqldump"
    )

    # 2. 塞所有参数
    parser.add_argument("outfile", help="备份文件的本地路径(不带.gz后缀)")
    parser.add_argument("--host", default="localhost", help="MySQL 主机地址")
    
    def check_port(port_str):
        port = int(port_str)
        if 1 <= port <= 65535:
            return port
        raise argparse.ArgumentTypeError(f"端口必须在 1-65535 之间")
    parser.add_argument("--port", type=check_port, default=3306, help="MySQL 端口号")
    
    parser.add_argument("-u", "--user", required=True, help="登录用户名")
    parser.add_argument("-p", "--password", required=True, help="登录密码")
    parser.add_argument("--database", required=True, help="要备份的数据库名")
    parser.add_argument("-g", "--gz", action="store_true", help="启用 GZIP 压缩")

    # 3. 解析+运行
    args = parser.parse_args()
    backup_database(
        args.outfile,
        args.host,
        args.port,
        args.user,
        args.password,
        args.database,
        args.gz
    )

现在试试 -h 看自动生成的文档:

python db_backup.py -h

输出会非常清晰,完全不需要手动写!


2.4 进阶:分组+子命令

如果工具参数超过 10 个,或者有多个独立功能(比如“备份”和“恢复”),可以用分组子命令优化用户体验。

参数分组

把相关的参数放在一起显示:

# 分组1:连接配置
conn_group = parser.add_argument_group("连接配置", "关于 MySQL 服务器的设置")
conn_group.add_argument("--host", default="localhost")
conn_group.add_argument("--port", type=int, default=3306)
conn_group.add_argument("-u", "--user", required=True)
conn_group.add_argument("-p", "--password", required=True)

# 分组2:备份配置
backup_group = parser.add_argument_group("备份配置", "关于备份文件的设置")
backup_group.add_argument("outfile")
backup_group.add_argument("--format", choices=["sql", "csv"], default="sql")
backup_group.add_argument("-g", "--gz", action="store_true")

子命令

相当于把一个大工具拆成多个小工具,比如 git add/git commit

import argparse

if __name__ == "__main__":
    parser = argparse.ArgumentParser(prog="db_tool", description="MySQL 管理工具集")
    # 必须加 dest='command',这样解析后才能知道用户选了哪个子命令
    subparsers = parser.add_subparsers(dest="command", required=True, help="可用的子命令")

    # --------------------------
    # 子命令1:backup
    # --------------------------
    backup_parser = subparsers.add_parser("backup", help="备份数据库到本地")
    backup_parser.add_argument("outfile", help="输出文件路径")
    # 这里可以复用之前的分组/参数...

    # --------------------------
    # 子命令2:restore
    # --------------------------
    restore_parser = subparsers.add_parser("restore", help="从本地文件恢复数据库")
    restore_parser.add_argument("infile", help="输入的备份文件路径")
    # 同样可以复用...

    args = parser.parse_args()
    if args.command == "backup":
        print("执行备份逻辑")
    elif args.command == "restore":
        print("执行恢复逻辑")

3. 现代替代方案(需要安装)

虽然 argparse 足够强大,但如果你追求更简洁的语法或者交互式输入,可以试试这两个第三方库:

3.1 Click

语法非常优雅,用装饰器代替手动创建 parser:

import click

@click.command()
@click.argument("outfile")
@click.option("--host", default="localhost", help="MySQL 主机")
@click.option("--port", default=3306, type=int, help="MySQL 端口")
@click.option("-u", "--user", required=True, help="用户名")
@click.password_option("-p", "--password", help="密码")  # 自带密码隐藏功能!
@click.option("-g", "--gz", is_flag=True, help="启用压缩")
def db_backup(outfile, host, port, user, password, gz):
    click.echo(f"备份到 {outfile}")

if __name__ == "__main__":
    db_backup()

安装方式:pip install click


3.2 Typer(基于 Click)

完全基于 Python 类型提示(Type Hints),代码可读性拉满,还支持自动补全!

import typer

app = typer.Typer()

@app.command()
def backup(
    outfile: str,
    host: str = "localhost",
    port: int = 3306,
    user: str = typer.Option(..., help="用户名"),  # ...表示必填
    password: str = typer.Option(..., prompt=True, hide_input=True, help="密码"),  # 交互式输入密码
    gz: bool = typer.Option(False, "--gz", "-g", help="启用压缩")
):
    typer.echo(f"✅ 备份到 {outfile}")

if __name__ == "__main__":
    app()

安装方式:pip install typer


4. 最佳实践总结

  1. 加 help!加 help!加 help! 这是对用户(也是对未来的你)最基本的尊重
  2. 默认值要合理:比如端口默认 3306、格式默认 json
  3. 参数名要易懂:长选项尽量用完整单词,短选项选有意义的单字母
  4. 尽早验证:用 type 自定义验证函数,比解析后再检查更友好
  5. 复杂工具用子命令:不要把所有参数堆在一个命令里

5. 快速决策表

场景推荐工具
临时脚本、1-2 个参数sys.argv
正式工具、不需要额外依赖argparse
喜欢装饰器语法、密码隐藏Click
喜欢类型提示、交互式补全Typer

总的来说,argparse 是所有 Python 开发者必须掌握的基础,其他第三方库可以根据项目需要选择学习~