ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python 内置模块 argparse快速入门教程

Python 内置模块 argparse快速入门教程 前言argparse是 Python 标准库里的命令行参数解析模块command-line argument parser。写脚本时如果要接收-v、--output 文件这类选项用它比手动切sys.argv可靠得多它会自动生成-h帮助、做类型转换、校验必填项、在出错时给出可读的提示。初学阶段有两个常见误解。第一以为argparse是第三方库要pip install——它是标准库直接import argparse即可。第二以为参数少自己切sys.argv也一样——手写版本一旦要支持--keyvalue、短选项合并、-h很快就会变成一堆难以维护的 if。还有一点要提前说清argparse在参数不合法时默认会打印用法并直接退出进程抛SystemExit这在测试里很不方便。Python 3.9 起可以用exit_on_errorFalse改变这个行为。本文用最小示例讲清常用参数示例基于 Python 3.8用到更新版本才有的能力时会注明。一、最小可用示例# 适用于 Python 3.8import argparseparser argparse.ArgumentParser(proggreet,description打印问候语argparse 示例。,)parser.add_argument(name, help要问候的名字)parser.add_argument(-n, --times, typeint, default1, help重复次数默认 1)parser.add_argument(-v, --verbose, actionstore_true, help输出更多信息)args parser.parse_args()for _ in range(args.times):print(f你好{args.name})if args.verbose:print(f一共重复了 {args.times} 次)保存为greet.py后python greet.py 世界python greet.py 世界 -n 3 -vpython greet.py --helpparse_args()从sys.argv[1:]取参数返回一个Namespace对象取值用属性访问args.name、args.times。二、构造函数参数ArgumentParser的完整签名较长按需了解ArgumentParser(progNone, usageNone, descriptionNone, epilogNone,parents[], formatter_classargparse.HelpFormatter, prefix_chars-,fromfile_prefix_charsNone, argument_defaultNone, conflict_handlererror,add_helpTrue, allow_abbrevTrue, exit_on_errorTrue, *,suggest_on_errorFalse, colorTrue)常用的几个参数作用备注prog帮助里显示的程序名默认按sys.argv[0]推导3.14 起默认值更贴近实际调用方式description参数说明前的描述文字帮助页顶部展示epilog说明之后的补充文字帮助页底部展示add_help是否自动加-h/--help默认True已有-h参数时设Falseallow_abbrev是否允许长选项缩写默认True--verb能匹配到--verboseexit_on_error出错时是否直接退出默认TrueFalse需3.9parents用来复用一组公共参数比如多个子命令共享--verbose写法是把一个add_helpFalse的父解析器传进去。三、add_argument 的常用参数签名很长实操中真正高频的是下面这些参数含义示例名字/选项位置参数写名字可选参数写-s/--longfile、-o、--outputtype值转换函数typeint、typefloat、typeopendefault未提供时的取值default1required是否必填只对可选参数有意义requiredTruechoices取值白名单choices[json, csv]nargs接收几个值?、*、、数字action如何处理store_true、store_false、count、appenddest结果存到哪个属性名destoutputmetavar帮助里显示的占位名metavarFILEhelp帮助文字help输出文件名字与属性名的对应关系值得单独记--output-file会被转成args.output_file连字符换下划线。想固定成别的名字就用dest。四、位置参数与可选参数位置参数add_argument(name)按顺序匹配默认就是必填。可选参数add_argument(-o, --output)可省required默认为False。# 适用于 Python 3.8import argparseparser argparse.ArgumentParser(description批量处理文件)parser.add_argument(files, nargs, help至少一个输入文件)parser.add_argument(-f, --format, choices[json, csv], defaultjson,help输出格式默认 json)parser.add_argument(--tag, actionappend,help可重复指定出现多次就收集多次)args parser.parse_args()tags args.tag or [] # 没提供时是 None兜一下更省心print(文件:, args.files)print(格式:, args.format)print(标签:, tags)nargs的取值语义要记牢写法含义未提供时不写恰好一个值位置参数必填可选参数取default?0 或 1 个取default可能是None*0 或多个空列表[]1 或多个报错3恰好 3 个报错action的常见取值action效果store默认存一个值store_true/store_false出现即为True/Falsecount计数-vvv得3append每次出现追加一个值store_const出现时存const指定的常量五、子命令与测试友好写法子命令适合像git add/git commit这种多动作的工具# 适用于 Python 3.8import argparseparser argparse.ArgumentParser(progtool, description带子命令的示例)parser.add_argument(-v, --verbose, actionstore_true)sub parser.add_subparsers(destcommand, requiredTrue)add_p sub.add_parser(add, help新增一条)add_p.add_argument(item)del_p sub.add_parser(del, help删除一条)del_p.add_argument(item)args parser.parse_args()print(子命令:, args.command, | 条目:, args.item, | verbose:, args.verbose)add_subparsers(destcommand, requiredTrue)让args.command记录选了哪个子命令requiredTrue要求必须给一个需要 Python 3.7。有一个必须记住的顺序问题顶层解析器的选项要写在子命令之前。-v add 苹果能识别-v而add 苹果 -v会把-v交给子解析器子解析器不认识它最终报unrecognized arguments。要在单元测试里调用解析逻辑不要让代码去读全局的sys.argv把参数列表传进去# 适用于 Python 3.8args parser.parse_args([-v, add, 苹果]) # -v 必须在子命令之前assert args.command addassert args.item 苹果assert args.verbose is Trueparse_args(argsNone, namespaceNone)的args就是为此设计的不传才用sys.argv[1:]。常见坑点坑 1忘记typeint拿到的是字符串。❌parser.add_argument(-n, default1)之后args.n * 2在传了-n 3时得到33。✅parser.add_argument(-n, typeint, default1)。坑 2给布尔选项写typebool。❌parser.add_argument(--flag, typebool)—— 命令行上传的是字符串bool(False)是Truebool()才是False行为完全反直觉。✅ 用actionstore_true出现即True或actionstore_false。坑 3给位置参数加requiredTrue。❌parser.add_argument(file, requiredTrue)—— 抛TypeError位置参数本身必填required只对可选参数有效。✅ 直接parser.add_argument(file)要它可有可无就nargs?。坑 4用--output-file却按args.output-file取。❌args.output-file是减法表达式不是属性访问直接AttributeError。✅ 属性名是args.output_file想换名字用dest。坑 5actionappend没提供参数时以为是空列表。❌for t in args.tag:—— 没传--tag时args.tag是None抛TypeError: NoneType object is not iterable。✅for t in (args.tag or []):或者显式给default[]并清楚它的语义。坑 6parse_args出错直接退出测试里接不住。❌ 在测试里期望捕获普通异常结果进程被SystemExit结束。✅ 用exit_on_errorFalse需 3.9让它在参数错误时抛ArgumentError或者测试时断言SystemExit并用pytest.raises/assertRaises包住。坑 7add_helpTrue与自定义-h冲突。❌ 自己add_argument(-h, --host)然后解析器初始化时就因重复选项报错。✅ArgumentParser(add_helpFalse)后再自己加-h并手动补一个--help。坑 8choices忘了写导致非法值穿透到业务代码。❌ 只add_argument(--format)用户传--format xml也照过后面if/elif全部落空。✅add_argument(--format, choices[json, csv])让 argparse 在入口就拦住非法值。总结需求写法备注创建解析器argparse.ArgumentParser(prog..., description...)标准库无需安装必填参数add_argument(name)位置参数天然必填可选参数add_argument(-n, --times)属性名把连字符换成下划线类型转换typeint/typefloat不写就是字符串布尔开关actionstore_true不要写typebool取值白名单choices[...]入口拦截非法值多值nargs/*/?注意未提供时的取值重复选项actionappend未提供时是None子命令add_subparsers(dest...)必填加requiredTrue测试友好parse_args([...])不要依赖全局sys.argv把argparse用顺的关键只有三步用type和choices在入口做校验、用action表达开关/计数/追加这类语义、把参数列表当参数传以便测试。-h帮助是它免费送的因此每个参数都值得写一句help文字——那才是给别人和三个月后的自己看的接口文档。Python 2 里也有argparse2.7 起加入但 Python 2 的print是语句、raw_input()已更名为input()写法与 Python 3 有差异。Python 2.7 自 2020 年 1 月 1 日停止维护新脚本一律用 Python 3。
返回列表