检查是否设置了 argparse 可选参数

我想检查一下用户是否设置了可选的 arparse 参数。

我可以安全地使用 isset 检查吗?

就像这样:

if(isset(args.myArg)):
#do something
else:
#do something else

这对 float/int/string 类型的参数是否同样适用?

我可以设置一个默认参数并检查它(例如,设置 myArg = -1,或“”为字符串,或“ NOT _ SET”)。但是,我最终想要使用的值只能在脚本的后面计算。所以我将它设置为 -1作为默认值,然后在以后更新它。与简单地检查用户是否设置了值相比,这似乎有点笨拙。

212799 次浏览

我认为如果没有提供可选参数(用 --指定) ,那么它们将被初始化为 None。所以你可以用 is not None来测试。试试下面的例子:

import argparse


def main():
parser = argparse.ArgumentParser(description="My Script")
parser.add_argument("--myArg")
args, leftovers = parser.parse_known_args()


if args.myArg is not None:
print "myArg has been set (value is %s)" % args.myArg

正如@Honza 指出的那样,is None是一个很好的测试。它是默认的 default,用户不能给你一个复制它的字符串。

您可以指定另一个 default='mydefaultvalue',并对其进行测试。但是,如果用户指定了该字符串,该怎么办呢?这算不算设定?

也可以指定 default=argparse.SUPPRESS。然后,如果用户不使用该参数,它将不会出现在 args名称空间中。但测试可能更为复杂:

parser.add_argument("--foo", default=argparse.SUPPRESS)


# ...


args.foo # raises an AttributeError
hasattr(args, 'foo')  # returns False
getattr(args, 'foo', 'other') # returns 'other'

在内部,parser保留 seen_actions的列表,并将其用于“必需的”和“互斥的”测试。但是在 parse_args之外是不可用的。

如果您的参数是 位置(即它没有“-”或“——”前缀,只有参数,通常是一个文件名) ,那么您可以使用 Nargs 参数来完成:

parser = argparse.ArgumentParser(description='Foo is a program that does things')
parser.add_argument('filename', nargs='?')
args = parser.parse_args()


if args.filename is not None:
print('The file name is {}'.format(args.filename))
else:
print('Oh well ; No args, no problems')

下面是我的解决方案,看看我是否使用了 argparse 变量

import argparse


ap = argparse.ArgumentParser()
ap.add_argument("-1", "--first", required=True)
ap.add_argument("-2", "--second", required=True)
ap.add_argument("-3", "--third", required=False)
# Combine all arguments into a list called args
args = vars(ap.parse_args())
if args["third"] is not None:
# do something

这可能会让我对上面的答案有更多的了解,我使用了这个答案,并对它进行了调整,以便为我的程序工作。

您可以选择使用 store_truestore_false参数操作选项检查传递的标志:

import argparse


argparser = argparse.ArgumentParser()
argparser.add_argument('-flag', dest='flag_exists', action='store_true')


print argparser.parse_args([])
# Namespace(flag_exists=False)
print argparser.parse_args(['-flag'])
# Namespace(flag_exists=True)

这样,您就不必担心通过条件 is not None进行检查。您只需检查 TrueFalse。阅读更多关于这些选项的文档 给你

我认为使用 default=argparse.SUPPRESS选项是最有意义的。然后,不检查参数是否为 not None,而是检查参数是否为 in,这样就得到了名称空间。

例如:

import argparse


parser = argparse.ArgumentParser()
parser.add_argument("--foo", default=argparse.SUPPRESS)
ns = parser.parse_args()


print("Parsed arguments: {}".format(ns))
print("foo in namespace?: {}".format("foo" in ns))

用法:

$ python argparse_test.py --foo 1
Parsed arguments: Namespace(foo='1')
foo in namespace?: True
没有提供参数:
$ python argparse_test.py
Parsed arguments: Namespace()
foo in namespace?: False

为了解决@kcpr 对@Honza Osobne 回答(目前已被接受)的评论

不幸的是,它不工作,然后参数得到了它的默认值 定义。

首先,可以通过与 Namespace对象进行比较并提供 default=argparse.SUPPRESS选项(参见@hpaulj 和@Erasmus Cedernaes 的答案和这个 Python3文档)来检查参数是否已经提供,如果没有提供,则将其设置为默认值。

import argparse


parser = argparse.ArgumentParser()
parser.add_argument('--infile', default=argparse.SUPPRESS)
args = parser.parse_args()
if 'infile' in args:
# the argument is in the namespace, it's been provided by the user
# set it to what has been provided
theinfile = args.infile
print('argument \'--infile\' was given, set to {}'.format(theinfile))
else:
# the argument isn't in the namespace
# set it to a default value
theinfile = 'your_default.txt'
print('argument \'--infile\' was not given, set to default {}'.format(theinfile))

用法

$ python3 testargparse_so.py
argument '--infile' was not given, set to default your_default.txt


$ python3 testargparse_so.py --infile user_file.txt
argument '--infile' was given, set to user_file.txt

非常简单,在通过‘ args = parser.parse _ args ()’定义 args 变量之后,它也包含了 args 子集变量的所有数据。要检查是否设置了变量,假设使用了‘ action = “ store _ true”..。

if args.argument_name:
# do something
else:
# do something else

自定义操作可以处理这个问题,我发现它并不复杂。

is_set = set() #global set reference
class IsStored(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
is_set.add(self.dest) # save to global reference
setattr(namespace, self.dest + '_set', True) # or you may inject directly to namespace
setattr(namespace, self.dest, values) # implementation of store_action
# You cannot inject directly to self.dest until you have a custom class




parser.add_argument("--myarg", type=int, default=1, action=IsStored)
params = parser.parse_args()
print(params.myarg, 'myarg' in is_set)
print(hasattr(params, 'myarg_set'))

这里有一个略有不同的方法:
假设您知道参数名称,那么您可以执行以下操作:

import sys


def is_set(arg_name):
if arg_name in sys.argv:
return True
return False

这样,您就不需要改变参数解析器,仍然可以添加自定义逻辑。