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

Posted

技术标签:

【中文标题】检查是不是设置了 argparse 可选参数【英文标题】:Check if argparse optional argument is set or not检查是否设置了 argparse 可选参数 【发布时间】:2015-08-09 20:27:00 【问题描述】:

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

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

类似这样的:

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

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

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

【问题讨论】:

isset() 会是什么(提示:Python 不是 php)?你的意思是hasattr() 吗?为什么不配置 argparse 来为选项设置默认值? @MartijnPieters - 是的,是的。那么我可以简单地检查一下 if(args.myArg): ... 【参考方案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

【讨论】:

“is None”和“is not None”测试完全符合我的期望。谢谢。 不幸的是它不起作用然后参数得到它的default值定义。 如果您想设置default,那么您仍然可以设置nargs='?' 并提供const 值,如in the docs 所述。当 arg 不存在时,使用 default,当 arg 给定 w/o 值时,则使用 const,否则使用给定值。只有defaultnargs='?',如果没有给出default,如果给出没有值,则使用None,否则给出值。 @IoannisFilippidis 如果您使用 action= "store_true"action="store_const", const="yourconst" 您不能使用该参数来存储其他值。这在使用默认值时不起作用。在我自己的情况下,我已经从 argparser 中删除了所有默认值,并在另一个函数 def defaults(): 中处理了所有默认值,我在其中按我想要的顺序混合了 ConfigParser、ArgumentParser 和默认值 @erm3nda 我没有提到设置action。答案不使用action。您提到的操作被记录为以一种特定的方式表现(如您所观察到的)。不过,没有必要定义一个动作。【参考方案2】:

正如@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 之外,您无法使用它。

【讨论】:

【参考方案3】:

我认为使用选项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

【讨论】:

这在 Python 3.7.5 (Anaconda) 下对我不起作用。我得到结果testfoo.py: error: argument --foo: expected one argument 我只是按照答案中的说明复制并粘贴了您的代码。也许你应该编辑它?我最终在我的实际代码中使用了下面的action='store_true' 答案。 @MikeWise 你是否以python argparse_test.py --foo 1 运行脚本? 这是否也适用于互斥组?【参考方案4】:

您可以使用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

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

【讨论】:

这并不能确定是否设置了具有值的参数。这里的主要问题是要知道 args 值是来自 defaul="" 还是由用户提供。【参考方案5】:

如果您的参数是位置(即它没有“-”或“--”前缀,只有参数,通常是文件名),那么您可以使用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')

【讨论】:

【参考方案6】:

为了解决@kcpr 对@Honza Osobne 的(当前接受的)答案的评论

不幸的是它不起作用然后参数得到了它的默认值 已定义。

首先可以通过将参数与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

【讨论】:

【参考方案7】:

这是我是否使用 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

这可能会更深入地了解我使用并适用于我的程序的上述答案。

【讨论】:

【参考方案8】:

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

import sys

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

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

【讨论】:

这是个好主意,但有一个问题:argparse 允许在没有歧义的情况下对可选参数进行部分匹配。 (例如,如果您有一个标志 --option,那么如果没有其他以 "opt" 开头的标志,--opt 将起作用。)如果您在 sys.argv 中查找以开头的条目,则可以修改此方法以使其正常工作但是,具有选项中最短的唯一部分。【参考方案9】:

自定义操作可以解决此问题。而且我发现它并没有那么复杂。

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'))

【讨论】:

【参考方案10】:

很简单,通过 'args = parser.parse_args()' 定义 args 变量后,它也包含了 args 子集变量的所有数据。假设使用了 'action="store_true" 来检查是否设置了变量...

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

【讨论】:

以上是关于检查是不是设置了 argparse 可选参数的主要内容,如果未能解决你的问题,请参考以下文章

Argparse:“可选参数”下列出的必需参数?

如何检查是不是设置了可选功能参数

如何检查调用者是不是设置了 PowerShell 可选参数

使用不需要指定输出文件名的可选参数运行 argparse

Python 2.7 argparse:如何正确嵌套可选的互斥参数?

argparse 必需参数列表与可选参数列表竞争