0

我想知道哪些选项是通过命令行显式传递的。

考虑以下 argparse 设置test.py

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 或任何其他更好的方法可以让我这样做?

4

4 回答 4

0

只需不设置默认值。如果未设置变量,则用户没有传递它。检查后,您可以自己处理默认值。

于 2013-09-26T07:22:10.233 回答
0

使用“store_true”操作,内置默认值为“False”

parser.add_argument('--foo',action='store_true')

没有输入产生

Namespace(foo=False)

而 '--foo' 产生

Namespace(foo=True)

parser.add_argument('--foo',action='store_true', default=True)

它总是foo=True。这种说法是没有用的。使用“store_true”或“store_false”时不要设置自己的默认值。

如果你想知道用户是否给你a --foo,使用第一种形式,并检查命名空间值是否为真。如果在以后的代码中你需要foo不管True用户给你什么,在你使用argparse.

于 2013-09-26T22:43:03.093 回答
0

这里的答案和评论建议不要设置默认值,然后在代码中自己处理默认值。然而,这些add_argument电话并不完全在我的控制之下,所以这不是一个真正的选择。

最初,我检查了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_defaults方法,但是所需的添加是微不足道的。

于 2014-01-26T17:10:35.093 回答
0

使用该ArgumentParser.get_default(dest)方法可以做到这一点。基本上,您遍历所有已解析的参数并收集哪些不等于默认值:

args = parser.parse_args()
non_default = {arg: value for (arg, value) in vars(args).iteritems() if value != parser.get_default(arg)}

尽管这在您的特定示例中不起作用,因为--foo它是一个无所事事的参数(它将变量设置为默认值)。

于 2015-01-13T00:27:40.670 回答