Python 命令行开关:别用 type=bool 解析 False
给脚本增加一个“预演”开关时,很容易写出 parser.add_argument('--dry-run', type=bool)。调用者输入 --dry-run False,程序却进入了预演分支。这不是 argparse 忽略了参数,而是 bool() 的含义与我们想要的文本解析不同。
1. 非空字符串都是真值
argparse 的 type 接收转换函数。命令行传入的是字符串,因此 type=bool 实际执行了类似下面的转换:
print(bool('False')) # True
print(bool('0')) # True
print(bool('')) # False
bool() 判断对象的真值,不负责识别英文单词。只要字符串非空,False、no、0 都会得到 True。这类问题通常不会报错,反而容易让定时脚本在错误的分支继续运行。
2. 开关用“是否出现”表达
如果需求只有开启和关闭,优先让参数本身表示动作,不再额外接收一个值。下面的完整脚本可保存为 flags.py,使用 Python 3 标准库运行:
import argparse
def build_parser():
parser = argparse.ArgumentParser(description='查看脚本执行选项')
parser.add_argument(
'--dry-run',
action='store_true',
help='只预览计划,不执行实际操作',
)
parser.add_argument(
'--verbose',
action='store_true',
help='显示详细信息',
)
return parser
if __name__ == '__main__':
args = build_parser().parse_args()
print(f'dry_run={args.dry_run}, verbose={args.verbose}')
运行结果如下:
python flags.py
dry_run=False, verbose=False
python flags.py --dry-run
dry_run=True, verbose=False
python flags.py --dry-run --verbose
dry_run=True, verbose=True
store_true 在参数缺席时默认为 False,出现时保存 True;连字符形式的 --dry-run 会映射为属性 dry_run。此时不要再写 --dry-run False,因为这个开关不接受后续值,多出的 False 会被当作无法识别的参数,解析器报错并以状态码 2 退出。
这里的脚本只打印选项,演示解析行为。真实程序仍须在执行写入、发送或删除操作之前检查 args.dry_run,仅仅定义开关不会自动阻止副作用。
3. 默认开启时提供明确的关闭方式
假设“彩色输出”默认开启,同时希望支持 --color 和 --no-color,Python 3.9 及以上可使用:
parser.add_argument(
'--color',
action=argparse.BooleanOptionalAction,
default=True,
help='开启或关闭彩色输出',
)
未传参数时 args.color 为 True,--no-color 得到 False,--color 得到 True。如果同时提供这两个选项,后出现的选项生效;自动生成命令时,最好只输出其中一个,减少阅读歧义。旧版 Python 可用互斥参数组配合 store_true、store_false 和显式默认值实现相近接口。
如果外部系统已经约定必须传入 --enabled true 这种格式,就应编写明确的字符串转换函数,只接受约定集合,并对未知值抛出 argparse.ArgumentTypeError。不要把无法识别的值静默当作 False。
一个布尔参数的接口需要同时说清三件事:不传时是什么值,开启时怎样写,关闭时怎样写。让 --help 与实际调用示例保持一致,比依赖调用者猜测 False 的含义更可靠。
- 点赞
- 收藏
- 关注作者
评论(0)