如何在python中使用argparse获得用户指定的不包含默认值的可选命令行arg列表?
我想知道哪些选项是通过命令行显式传递的 考虑如何在python中使用argparse获得用户指定的不包含默认值的可选命令行arg列表?,python,command-line,command-line-arguments,argparse,Python,Command Line,Command Line Arguments,Argparse,我想知道哪些选项是通过命令行显式传递的 考虑test.py中的以下argparse设置: parser.add_argument("--foo", default=True, action="store_true") parser.add_argument("--bar", default=False, action="store_true") 当我执行/test.py--foo--bar时,我将在命名空间中获得foo=True,bar=True。 在这种情况下,--foo和--bar通过命令
test.py
中的以下argparse设置:
parser.add_argument("--foo", default=True, action="store_true")
parser.add_argument("--bar", default=False, action="store_true")
当我执行/test.py--foo--bar
时,我将在命名空间中获得foo=True
,bar=True
。在这种情况下,
--foo
和--bar
通过命令行显式传递
当我执行/test.py--bar
时,我仍然会在名称空间中得到foo=True
,bar=True
因此,我需要在不牺牲默认功能的情况下,找出在通过命令行执行时实际传递了哪些参数(在第二种情况下:--bar
)
一种方法是在argv
中搜索,但效率不高,看起来也不优雅。
我想知道,是否有任何argparse api或其他更好的方法允许我这样做?只需设置无默认值即可。如果未设置变量,则用户未传递该变量。检查后,您可以自己处理默认值。通过“store\u true”操作,内置默认值为“False” 与 没有投入就没有产出
Namespace(foo=False)
而“--foo”产生
Namespace(foo=True)
与
它总是foo=True
。那论点毫无用处。使用“store\u true”或“store\u false”时,不要设置自己的默认值
如果您想知道用户是否给了您一个
--foo
,请使用第一个表单,并检查名称空间值是否为true。如果在以后的代码中,无论用户给了您什么,您都需要foo
成为True
,请在使用argparse
后明确设置,此处的答案和注释建议不要设置默认值,然后在代码中自行处理默认值。但是,add_参数
调用并不完全在我的控制之下,因此这不是一个真正的选项
最初,我检查了sys.argv
中是否存在选项。这种方法很快被证明是低效的,容易出现错误,而且根本不可扩展
最后,我得出了这样的结论,似乎效果很好:
class _Reflection(object):
def __init__(self, source, reflection, name=None):
self.source = source
self.reflection = reflection
self.name = name
def __getattr__(self, attribute):
self.attribute = attribute
return _Reflection(self.source.__getattribute__(attribute), self.reflection.__getattribute__(attribute), name=attribute)
def __call__(self, *args, **kwargs):
source_output = self.source(*args, **kwargs)
if self.name == 'add_argument':
# if the method being called is 'add_argument',
# over-ride the 'default' argument's value to 'None' in our secondary argparser.
kwargs['default'] = None
reflection_output = self.reflection(*args, **kwargs)
return _Reflection(source_output, reflection_output)
class ReflectionArgumentParser(object):
def create(self, *args, **kwargs):
self.parser = argparse.ArgumentParser(*args, **kwargs)
self._mirror = argparse.ArgumentParser(*args, **kwargs)
return _Reflection(self.parser, self._mirror)
def parse_args(self, *args, **kwargs):
return self.parser.parse_args(*args, **kwargs)
def filter_defaults(self, *args, **kwargs):
return self._mirror.parse_args(*args, **kwargs)
mirrorParser = ReflectionArgumentParser()
parser = mirrorParser.create()
parser.add_argument('-f', '--foo', default=False, action="store_true")
parser.add_argument('-b', '--baz', default=0, action="store_const", const=10)
parser.add_argument('bar', nargs='*', default='bar')
print mirrorParser.parse_args([])
# Outputs: Namespace(bar='bar', baz=0, foo=False)
print mirrorParser.filter_defaults([])
# Outputs: Namespace(bar=[], baz=None, foo=None)
print mirrorParser.filter_defaults('--foo -b lorem ipsum'.split())
# Outputs: Namespace(bar=['lorem', 'ipsum'], baz=10, foo=True)
我已经用参数组和子参数尝试了这个实现。这不处理
set\u defaults
方法,但是所需的添加非常简单。这可以使用ArgumentParser.get\u default(dest)
方法实现。
基本上,您迭代所有解析的参数,并收集哪些参数不等于默认值:
args = parser.parse_args()
non_default = {arg: value for (arg, value) in vars(args).iteritems() if value != parser.get_default(arg)}
虽然这在您的特定示例中不起作用,因为
--foo
是一个不做任何事情的参数(它将变量设置为默认值)。您不能。这就是默认设置的用途。必须坚持在argv
中搜索,似乎:(
class _Reflection(object):
def __init__(self, source, reflection, name=None):
self.source = source
self.reflection = reflection
self.name = name
def __getattr__(self, attribute):
self.attribute = attribute
return _Reflection(self.source.__getattribute__(attribute), self.reflection.__getattribute__(attribute), name=attribute)
def __call__(self, *args, **kwargs):
source_output = self.source(*args, **kwargs)
if self.name == 'add_argument':
# if the method being called is 'add_argument',
# over-ride the 'default' argument's value to 'None' in our secondary argparser.
kwargs['default'] = None
reflection_output = self.reflection(*args, **kwargs)
return _Reflection(source_output, reflection_output)
class ReflectionArgumentParser(object):
def create(self, *args, **kwargs):
self.parser = argparse.ArgumentParser(*args, **kwargs)
self._mirror = argparse.ArgumentParser(*args, **kwargs)
return _Reflection(self.parser, self._mirror)
def parse_args(self, *args, **kwargs):
return self.parser.parse_args(*args, **kwargs)
def filter_defaults(self, *args, **kwargs):
return self._mirror.parse_args(*args, **kwargs)
mirrorParser = ReflectionArgumentParser()
parser = mirrorParser.create()
parser.add_argument('-f', '--foo', default=False, action="store_true")
parser.add_argument('-b', '--baz', default=0, action="store_const", const=10)
parser.add_argument('bar', nargs='*', default='bar')
print mirrorParser.parse_args([])
# Outputs: Namespace(bar='bar', baz=0, foo=False)
print mirrorParser.filter_defaults([])
# Outputs: Namespace(bar=[], baz=None, foo=None)
print mirrorParser.filter_defaults('--foo -b lorem ipsum'.split())
# Outputs: Namespace(bar=['lorem', 'ipsum'], baz=10, foo=True)
args = parser.parse_args()
non_default = {arg: value for (arg, value) in vars(args).iteritems() if value != parser.get_default(arg)}