Python argparse
解析命令行参数为布尔值¶
在 Python 开发中,命令行参数解析是一个常见的需求,它允许我们以命令行的方式向程序传递参数,从而实现更灵活和可配置的程序设计。Python 提供了一个内置库 argparse
,它简化了命令行参数解析的过程。
这篇帖子介绍过如何使用 argparse
解析命令行参数,本文将介绍如何指定命令行参数为布尔值类型。直接使用 type=bool
是无法实现的,而需要传入一个 callable
的对象,在其中编写将字符串转换为布尔值的逻辑。
尝试指定 type=bool
¶
首先我们尝试指定 type=bool
:
Python
import argparse
parser = argparse.ArgumentParser("test")
parser.add_argument("--yesorno", type=bool, default=True)
args = parser.parse_args()
yesorno = args.yesorno
print(type(yesorno))
print(yesorno)
在命令行中运行:
可以看到,即使提供的参数为 False
,但程序仍然解析为了 True
。这是因为 argparse
会将我们提供的 False
当作是一个字符串,再对这个字符串进行判断是否为 True
,而字符串 bool("False")
的结果是 True
。
使用 type=lambda x: (str(x).lower() == 'true')
¶
参考 Stackoverflow 的回答,我们可以对 type
传入一个 callable
的对象,在其中编写将字符串转换为布尔值的逻辑。
Python
import argparse
parser = argparse.ArgumentParser("test")
parser.add_argument(
"--yesorno", type=lambda x: (str(x).lower() == "true"), default=True
)
args = parser.parse_args()
yesorno = args.yesorno
print(type(yesorno))
print(yesorno)
考虑更全面的写法¶
有时用户并不只是提供 True
这样标准的写法,例如 yes
、y
、t
等等可能都代表真值含义。参考 Stackoverflow 的回答,我们可以定义更全面的判断逻辑:
Python
def str2bool(v):
if isinstance(v, bool):
return v
if v.lower() in ("yes", "true", "t", "y", "1"):
return True
elif v.lower() in ("no", "false", "f", "n", "0"):
return False
else:
raise argparse.ArgumentTypeError("Boolean value expected.")
或者参考 Stackoverflow 的回答的评论区,可以使用内置的 distutils.util.strtobool
,自动判断多种表达真值的字符串:
Python
import argparse
from distutils.util import strtobool
parser = argparse.ArgumentParser("test")
parser.add_argument("--yesorno", type=lambda x: bool(strtobool(str(x))), default=True)
args = parser.parse_args()
yesorno = args.yesorno
print(type(yesorno))
print(yesorno)
distutils.util.strtobool 的实现
Python
def strtobool(val):
"""Convert a string representation of truth to true (1) or false (0).
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
'val' is anything else.
"""
val = val.lower()
if val in ('y', 'yes', 't', 'true', 'on', '1'):
return 1
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
return 0
else:
raise ValueError("invalid truth value {!r}".format(val))