Python command line parameter parsing tutorial

1. Basic introduction: sys.argv quick acquisition

If you just want to get the original string typed by the user,sys.argvis the fastest way. It is a list, the first element is always the name of the script itself (e.g.script.py), followed by any space-separated input.

import sys

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

Save the above code asbasic_argv.py, run in the terminal:

python basic_argv.py hello world 123

The output will be:

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

Although this method is straightforward, its shortcomings are also obvious: No type checking, no constraint logic, no help documentation - if the tool is slightly more complicated, you and your users will collapse.


2. Core tool: argparse standard library

As long as your command line tool requires a more formal user experience, Python comes withargparseThat's the first choice. It does not require additional installation and can be automatically generated-h/--helpHelp documentation and covers most command line scenarios.

2.1 Three steps to build the framework

useargparseThe process is very simple, only three steps:

  1. Create aArgumentParserObject (equivalent to a "parameter storage box")
  2. passadd_argument()Add various parameter rules to the box
  3. Callparse_args()Parse the parameters and get an attributed object
import argparse

# 第一步:搭建收纳箱
parser = argparse.ArgumentParser(
    prog="my_cli_tool",       # 工具的正式名称(帮助文档中显示)
    description="这是一个示例工具的简介",
    epilog="© 2024 我的开发笔记"  # 帮助文档结尾的附注
)

# 第二步:添加参数
parser.add_argument("file_path", help="要操作的文件路径")

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

It's that simple! runpython my_cli_tool.py -h, you will immediately see a clearly structured help message.

2.2 Five commonly used parameter types

① Positional parameters (required, no short/long options)

Positional parameters are bound in the order entered by the user, and are suitable for core content that logically must be filled in first, such as file paths and operation names.

parser.add_argument(
    "outfile",
    help="数据库备份的输出文件路径"  # 一定要写 help!
)

② Optional parameters (with short/long options)

Optional parameters can be given in any order, suitable for non-core content such as switches and configuration items. Short options are usually single letters (e.g.-u), long options are more readable (e.g.--user)。

parser.add_argument(
    "-u", "--user",    # 可以单独写 -u 或 --user,也可以同时写
    required=True,     # 可选参数也能变成必填
    help="登录数据库的用户名"
)

③ Optional parameters with default values

Setting default values ​​for optional parameters can reduce the user's burden. Default values ​​are listed in the help documentation.(default: xxx)automatically displayed.

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

④ Type conversion and verification

By default, all parameters are treated as strings. passtypecan be automatically converted tointfloatOther types, and even custom verification functions.

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

# 自定义验证:限制端口范围
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 端口号"
)

Tip: The custom validation function will immediately throw a clear error when the user enters an illegal value, which is a much better experience than parsing and then checking.

⑤ Boolean switch parameters

This parameter does not need to be followed by a value. As long as it appears in the command line, it will be automatically set toTrue(orFalse). passactionParameter control.

# 只要写 -g 就设为 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",  # 修改解析后对象的属性名
    default=True,
    help="是否禁用彩色输出"
)

⑥ Limit selected parameters

usechoicesLimit the input to a value in the specified list, and the help document will automatically list these options.

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

2.3 Complete practical example: database backup tool

Integrate the above knowledge points and write a simple but complete MySQL backup tool template.

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
    )

run nowpython db_backup.py -hTake a look at the automatically generated help document, and you will feel real peace of mind - you no longer have to write a bunch of instructions by hand.


2.4 Advanced: Grouping + Subcommands

When the number of parameters exceeds 10, or there are multiple independent functions in a tool (such as "backup" and "restore"), you can use grouping and subcommands to make the user's input more organized.

Parameter grouping

By grouping related parameters under the same heading, the help documentation immediately becomes clear:

# 分组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")

Subcommands

Subcommands are equivalent to splitting a large tool into several independent small commands, likegit addandgit commitThat way. usesubparsersCan be achieved easily.

import argparse

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

    # 子命令1:backup
    backup_parser = subparsers.add_parser("backup", help="备份数据库到本地")
    backup_parser.add_argument("outfile", help="输出文件路径")
    # 这里可以继续添加 --host、--user 等参数...

    # 子命令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. Modern alternative (requires installation)

AlthoughargparseIt is powerful enough, but if you are pursuing more concise syntax or more modern interactive experience, you can take a look at the following two third-party libraries.

3.1 Click

ClickUse decorators to define commands with very elegant syntax. It also thoughtfully provides functions such as password hiding.

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()

Install:pip install click

3.2 Typer (based on Click)

TyperFully embracing Python type hints, the readability and maintainability of the code are directly improved, and automatic completion is also supported.

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()

Install:pip install typer


4. Summary of best practices

  1. must be writtenhelp: This is the most basic respect for users (and yourself in the future)
  2. Set reasonable default values: For example, port default3306, format defaultjson
  3. Parameter naming should be intuitive: Try to use complete words for long options, and use meaningful single letters for short options.
  4. Validate input early: Take advantagetypeCustom verification function is much more friendly than checking after parsing
  5. Complex tools use subcommands: Avoid stacking all parameters together

5. Quick decision table

ScenarioRecommended Tools
Temporary script with only one or two parameterssys.argv
Formal tool, don’t want to introduce additional dependenciesargparse
Like decorator syntax, need password hidingClick
Obsessed with type prompts and want interactive completionTyper

No matter which one you end up choosing for your project,argparseThese are the basics that every Python developer must have a solid grasp of. On this basis, just choose more modern alternatives based on specific needs.