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

Check if argparse optional argument is set or not

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

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

像这样:

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

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

我可以设置一个默认参数并检查它(例如,设置 myArg = -1,或“”表示字符串,或 "NOT_SET")。但是,我最终要使用的值只是在脚本的后面计算。所以我会将其默认设置为 -1,然后稍后将其更新为其他内容。与简单地检查该值是否由用户设置相比,这似乎有点笨拙。

我认为如果未提供可选参数(用 -- 指定)将初始化为 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 的列表,并将其用于 'required' 和 'mutually_exclusive' 测试。但是 parse_args.

之外的您无法使用它

如果你的参数是位置(即它没有“-”或“--”前缀,只有参数,通常是文件名)那么你可以使用 the nargs parameter 来做到这一点:

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。在文档 here

中阅读有关这些选项的更多信息

我认为使用选项 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 的(当前接受的)回答的评论

Unfortunately it doesn't work then the argument got it's default value defined.

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

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

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