如何在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)}