上篇内容中我们了解了argparse的基础参数用法,今天我们一起实现多子命令工具、日志联动、完整实战项目,做出和git、docker、pip一样的专业级CLI工具
我们平时用的git、pip、docker,都是一个工具支持多个命令(比如git add、git commit),这种就是子命令,argparse通过add_subparsers()轻松实现,让一个脚本支持多种功能,结构更清晰。
import argparse# 创建主解析器parser = argparse.ArgumentParser(description="文章发布队列管理工具")# 添加子命令解析器,dest用于判断用户输入的命令subparsers = parser.add_subparsers(dest="command", required=True)# 1. 创建list子命令:查看队列list_parser = subparsers.add_parser("list", help="查看待发布文章队列")# 给子命令添加专属参数list_parser.add_argument("--format", choices=["table", "json"], default="table", help="展示格式")# 2. 创建publish子命令:发布文章publish_parser = subparsers.add_parser("publish", help="发布下一篇待发布文章")publish_parser.add_argument("--dry-run", action="store_true", help="模拟发布,不实际操作")
CLI工具常用--verbose/-v参数开启详细日志,方便调试,argparse可以轻松和Python内置logging模块联动,根据是否传-v自动切换日志级别:
import argparseimport loggingparser = argparse.ArgumentParser()parser.add_argument("--verbose", "-v", action="store_true", help="开启调试日志")args = parser.parse_args()# 根据verbose参数设置日志级别logging.basicConfig( level=logging.DEBUG if args.verbose else logging.INFO, format="%(levelname)s: %(message)s")# 日志使用log = logging.getLogger(__name__)log.info("工具启动成功") # 默认打印log.debug("调试信息:参数解析完成") # 只有加-v才会打印
用法:python test.py list -v 开启调试日志,不加-v则只打印普通信息,调试更方便。
接下来我们实现一个文章发布队列管理工具,包含list(查看队列)、add(添加文章)、publish(发布文章)三个子命令,涵盖argparse所有高频用法:
#!/usr/bin/env python3"""publish_queue.py — 文章发布队列管理CLI工具用法:python publish_queue.py <命令> [选项]"""import argparseimport jsonimport loggingimport sysfrom pathlib import Path# 队列存储文件QUEUE_FILE = Path("queue.json")def load_queue() -> list[dict]: """加载发布队列""" if not QUEUE_FILE.exists(): return [] return json.loads(QUEUE_FILE.read_text(encoding="utf-8"))def save_queue(queue: list[dict]) -> None: """保存发布队列""" QUEUE_FILE.write_text(json.dumps(queue, indent=2, ensure_ascii=False), encoding="utf-8")def cmd_list(args: argparse.Namespace) -> None: """list命令:展示发布队列""" queue = load_queue() if not queue: print("发布队列为空~") return for i, article in enumerate(queue, 1): status = "[已发布]" if article.get("published") else "[待发布]" tags = ", ".join(article.get("tags", [])) print(f"{i}. {status}{article['title']}(标签:{tags})")def cmd_add(args: argparse.Namespace) -> None: """add命令:添加文章到队列""" queue = load_queue() article = { "title": args.title, "tags": args.tags or [], "published": False, } queue.append(article) save_queue(queue) logging.info(f"已添加文章:{args.title}") print(f"成功添加「{args.title}」到队列,当前总文章数:{len(queue)}")def cmd_publish(args: argparse.Namespace) -> None: """publish命令:发布下一篇待发布文章""" queue = load_queue() pending_articles = [a for a in queue if not a.get("published")] if not pending_articles: print("暂无待发布文章~") return next_article = pending_articles[0] if args.dry_run: print(f"[模拟执行] 即将发布:{next_article['title']}") return # 标记为已发布 next_article["published"] = True save_queue(queue) print(f"成功发布:{next_article['title']}") logging.info(f"发布完成:{next_article['title']}")def build_parser() -> argparse.ArgumentParser: """构建argparse解析器""" parser = argparse.ArgumentParser( prog="publish_queue", description="个人文章发布队列管理工具", ) # 全局参数:日志级别 parser.add_argument("--verbose", "-v", action="store_true", help="开启调试日志") # 子命令配置 subparsers = parser.add_subparsers(dest="command", required=True, help="可用命令") # list子命令 list_parser = subparsers.add_parser("list", help="查看发布队列") list_parser.set_defaults(func=cmd_list) # add子命令 add_parser = subparsers.add_parser("add", help="添加文章到发布队列") add_parser.add_argument("--title", required=True, help="文章标题(必填)") add_parser.add_argument("--tags", nargs="*", help="文章标签,空格分隔") add_parser.set_defaults(func=cmd_add) # publish子命令 publish_parser = subparsers.add_parser("publish", help="发布下一篇待发布文章") publish_parser.add_argument("--dry-run", action="store_true", help="模拟发布,不修改数据") publish_parser.set_defaults(func=cmd_publish) return parserdef main() -> None: parser = build_parser() args = parser.parse_args() # 配置日志 logging.basicConfig( level=logging.DEBUG if args.verbose else logging.INFO, format="%(levelname)s: %(message)s" ) # 执行对应命令函数 args.func(args)if __name__ == "__main__": main()
可以通过help来查看各种执行参数。
最后,以后写Python脚本,花上10分钟用上argparse,让脚本变得更专业。