Python argparse:在 10 分钟内构建 CLI 工具
Source: Dev.to
🎁 免费: AI 出版清单 — 用 Python 的 7 步
完整流程:(随意付费,最低 $9.99)
问题
你写了一个快速脚本,硬编码了文件名,随后立刻需要更改它。于是你去使用 sys.argv:
import sys
filename = sys.argv[1]
count = int(sys.argv[2])
它能工作……直到它不工作为止:
- 不带参数运行 →
IndexError。 - 在需要整数的地方传入非整数 → 崩溃。
- 没有帮助文本,没有验证,没有默认值。
- 其他人要使用你的脚本时必须阅读源码才能知道如何运行。
为什么 argparse?
argparse(标准库)解决了所有这些问题。
一次调用 parse_args() 就能处理:
- 读取
sys.argv - 验证输入
- 打印帮助信息(
--help)
基本模板
import argparse
parser = argparse.ArgumentParser(
description="My CLI tool — does useful things."
)
args = parser.parse_args()
位置参数
必需的,并通过位置而非名称来标识:
parser.add_argument("filename", help="Path to the input file")
parser.add_argument("count", help="Number of items to process")
可选(标志)参数
使用 -- 前缀;短别名是可选的:
parser.add_argument(
"--output", "-o",
help="Output file path",
default="output.txt"
)
parser.add_argument(
"--verbose", "-v",
help="Enable verbose logging",
action="store_true"
)
类型转换与可选项
让 argparse 完成转换和验证:
parser.add_argument(
"--count", type=int, default=10,
help="Number of items"
)
parser.add_argument(
"--rate", type=float, default=1.5,
help="Processing rate"
)
parser.add_argument(
"--format",
choices=["json", "csv", "txt"],
default="json",
help="Output format"
)
如果用户运行 --count hello,argparse 会打印简洁的错误信息并退出——不会出现堆栈跟踪。
nargs 和列表
| 示例 | 含义 |
|---|---|
parser.add_argument("--title", required=True, help="Article title (required)") | 必需的可选参数 |
parser.add_argument("--tags", nargs="+", help="One or more tags") | 一个 或多个 值 (+) |
parser.add_argument("--tags", nargs="*", help="Zero or more tags") | 零个 或多个 值 (*) |
结果是一个 Python 列表,你可以直接迭代:
args = parser.parse_args()
for tag in args.tags:
print(tag)
布尔标志 (store_true / store_false)
parser.add_argument(
"--dry-run",
action="store_true",
help="Simulate without writing"
)
parser.add_argument(
"--no-color",
action="store_false",
dest="color",
help="Disable color output"
)
用法
python publish.py --dry-run # args.dry_run 为 True
python publish.py # args.dry_run 为 False
python publish.py --no-color # args.color 为 False
子命令(如 git、docker、pip)
parser = argparse.ArgumentParser(description="Publish queue manager")
subparsers = parser.add_subparsers(dest="command", required=True)
# `publish` subcommand
publish_parser = subparsers.add_parser(
"publish",
help="Publish the next article in queue"
)
publish_parser.add_argument(
"--dry-run",
action="store_true",
help="Simulate without publishing"
)
# `list` subcommand
list_parser = subparsers.add_parser(
"list",
help="Show the publish queue"
)
list_parser.add_argument(
"--format",
choices=["table", "json"],
default="table"
)
args.command 告诉你选择了哪个子命令,每个子命令都有自己的参数。
--verbose / -v 模式
一种常见的做法是使用 --verbose 在运行时设置日志级别:
import argparse
import logging
parser = argparse.ArgumentParser()
parser.add_argument(
"--verbose", "-v",
action="store_true",
help="Enable debug logging"
)
args = parser.parse_args()
logging.basicConfig(
level=logging.DEBUG if args.verbose else logging.INFO,
format="%(levelname)s: %(message)s"
)
log = logging.getLogger(__name__)
log.info("Starting...")
log.debug("This only shows with --verbose")
完整示例:文章发布队列 CLI
#!/usr/bin/env python3
"""
publish_queue.py — CLI for managing the article publish queue.
Usage: python publish_queue.py [options]
"""
import argparse
import json
import logging
import sys
from pathlib import Path
QUEUE_FILE = Path("queue.json")
def load_queue() -> list[dict]:
"""Load the queue from JSON; return empty list if file missing."""
if not QUEUE_FILE.exists():
return []
return json.loads(QUEUE_FILE.read_text())
def save_queue(queue: list[dict]) -> None:
"""Write the queue back to disk."""
QUEUE_FILE.write_text(json.dumps(queue, indent=2))
def cmd_list(args: argparse.Namespace) -> None:
queue = load_queue()
if not queue:
print("Queue is empty.")
return
for i, article in enumerate(queue, 1):
status = "[published]" if article.get("published") else "[pending] "
tags = ", ".join(article.get("tags", []))
print(f"{i}. {status} {article['title']} ({tags})")
def cmd_add(args: argparse.Namespace) -> None:
queue = load_queue()
article = {
"title": args.title,
"tags": args.tags or [],
"published": False,
}
queue.append(article)
save_queue(queue)
logging.info("Added: %s", args.title)
print(f"Added '{args.title}' to queue. Total: {len(queue)} articles.")
def cmd_publish(args: argparse.Namespace) -> None:
queue = load_queue()
pending = [a for a in queue if not a.get("published")]
if not pending:
print("No pending articles.")
return
next_article = pending[0]
if args.dry_run:
print(f"[DRY RUN] Would publish: {next_article['title']}")
return
next_article["published"] = True
save_queue(queue)
print(f"Published: {next_article['title']}")
logging.info("Published: %s", next_article["title"])
def main() -> None:
parser = argparse.ArgumentParser(
description="Publish queue manager"
)
subparsers = parser.add_subparsers(dest="command", required=True)
# add subcommand
add_parser = subparsers.add_parser(
"add",
help="Add a new article to the queue"
)
add_parser.add_argument(
"--title",
required=True,
help="Article title (required)"
)
add_parser.add_argument(
"--tags",
nargs="*",
help="Zero or more tags"
)
add_parser.set_defaults(func=cmd_add)
# list subcommand
list_parser = subparsers.add_parser(
"list",
help="Show the publish queue"
)
list_parser.set_defaults(func=cmd_list)
# publish subcommand
publish_parser = subparsers.add_parser(
"publish",
help="Publish the next pending article"
)
publish_parser.add_argument(
"--dry-run",
action="store_true",
help="Simulate without publishing"
)
publish_parser.set_defaults(func=cmd_publish)
# global verbose flag
parser.add_argument(
"--verbose", "-v",
action="store_true",
help="Enable debug logging"
)
args = parser.parse_args()
# configure logging *after* parsing arguments
logging.basicConfig(
level=logging.DEBUG if args.verbose else logging.INFO,
format="%(levelname)s: %(message)s"
)
# dispatch to the chosen subcommand
args.func(args)
if __name__ == "__main__":
main()
运行脚本:
python publish_queue.py add --title "My First Article" --tags python tutorial
python publish_queue.py list
python publish_queue.py publish --dry-run
python publish_queue.py publish -v
TL;DR
argparse将单行脚本转换为完善的 CLI。- 定义 positional(位置)和 optional(可选)参数,使用 type conversion(类型转换)、choices(可选值)和 nargs(参数数量)来处理列表。
- 使用
store_true/store_false来实现标志位。 - 利用 sub‑parsers 实现类似 git 的子命令。
- 添加
--verbose标志以切换日志输出。
试一试——你的脚本将在几分钟内变得更健壮、自动生成文档且更友好!
publish_queue.py – 基于 Argument‑Parser 的 CLI
import argparse
import logging
# Example logging call used by the script
logging.info("Published: %s", next_article["title"])
def build_parser() -> argparse.ArgumentParser:
"""Create the top‑level argument parser."""
parser = argparse.ArgumentParser(
prog="publish_queue",
description="Manage your article publish queue.",
)
parser.add_argument(
"--verbose", "-v",
action="store_true",
help="Enable debug logging",
)
subparsers = parser.add_subparsers(dest="command", required=True)
# ── list ────────────────────────────────────────────────────────
list_parser = subparsers.add_parser("list", help="Show the publish queue")
list_parser.set_defaults(func=cmd_list)
# ── add ────────────────────────────────────────────────────────
add_parser = subparsers.add_parser("add", help="Add an article to the queue")
add_parser.add_argument("--title", required=True, help="Article title")
add_parser.add_argument("--tags", nargs="*", help="Tags for the article")
add_parser.set_defaults(func=cmd_add)
# ── publish ─────────────────────────────────────────────────────
publish_parser = subparsers.add_parser(
"publish", help="Publish the next pending article"
)
publish_parser.add_argument(
"--dry-run", action="store_true", help="Simulate without writing"
)
publish_parser.set_defaults(func=cmd_publish)
return parser
def main() -> None:
"""Entry point for the CLI."""
parser = build_parser()
args = parser.parse_args()
logging.basicConfig(
level=logging.DEBUG if args.verbose else logging.INFO,
format="%(levelname)s: %(message)s",
)
# Dispatch to the appropriate sub‑command function
args.func(args)
if __name__ == "__main__":
main()
--help 输出
$ python publish_queue.py --help
usage: publish_queue [-h] [--verbose] {list,add,publish} ...
Manage your article publish queue.
positional arguments:
{list,add,publish}
list Show the publish queue
add Add an article to the queue
publish Publish the next pending article
options:
-h, --help show this help message and exit
--verbose, -v Enable debug logging
$ python publish_queue.py add --help
usage: publish_queue add [-h] --title TITLE [--tags [TAGS ...]]
options:
-h, --help show this help message and exit
--title TITLE Article title
--tags [TAGS ...] Tags for the article
示例工作流
# Add articles to the queue
python publish_queue.py add --title "Python argparse guide" \
--tags python beginners tutorial
python publish_queue.py add --title "Automate your workflow" \
--tags python automation
# List the queue
python publish_queue.py list
# 1. [pending] Python argparse guide (python, beginners, tutorial)
# 2. [pending] Automate your workflow (python, automation)
# Publish the next article (dry‑run first)
python publish_queue.py publish --dry-run
# [DRY RUN] Would publish: Python argparse guide
python publish_queue.py publish
# Published: Python argparse guide
# Check the updated queue with debug logging
python publish_queue.py list --verbose
Argparse 模式速查表
| 模式 | 何时使用 |
|---|---|
type=int / type=float | 任意数值输入 |
choices=[...] | 固定的一组有效值 |
required=True | 必需的可选参数 |
nargs="+" / nargs="*" | 值的列表 |
action="store_true" | 布尔标志 |
add_subparsers() | 多命令工具 |
set_defaults(func=…) | 分派到子命令函数 |
argparse 自动提供的功能
-h/--help– 从help=字符串生成- 类型验证 – 清晰的错误信息,无回溯
- 默认值 – 在帮助输出中记录
- 使用行 – 根据参数定义自动生成
不需要第三方库。 一切都使用 Python 标准库即可工作。
进一步阅读与资源
- 完整流水线中的 publish‑queue CLI – germy5.gumroad.com/l/xhxkzz(随意付费,最低 $9.99)
- 您的第一个自动化 Python 脚本:验证并自行运行
- Python 日志:停止在自动化脚本中使用
print() - 如何使用 Cron 调度 Python 脚本:初学者完整指南