检查是不是设置了 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
,否则使用给定值。只有default
和nargs='?'
,如果没有给出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_true
和store_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
进行检查。您只需检查True
或False
。在文档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 可选参数的主要内容,如果未能解决你的问题,请参考以下文章