1

我想为我的用户提供添加多个复杂对象的可能性,例如:Library 对象将是:

  • 图书馆名称
  • 图书馆号
  • ...

为此,我所做的是设置一个带有附加操作的参数 --library 并向参数添加一个类型,以便它以正确的格式读取它,这会导致以下命令行: --library "library_name=test;library_number =5”,库类型函数将测试并完成工作,但这并不是一个很好的方法,还有其他方法可以做我想要的吗?

我想像这样使用nargs:

--library test 5

这对我来说看起来更好,但是我想关联的类型函数不能是复杂的,因为它在返回数组的每个值上运行!

任何的想法?


我应该多解释一下我正在尝试做的事情。我正在开发工作流管理器引擎。这一个指定了一个属性文件,其中定义了所有参数,并且该参数列表被解析以构建正确的 argparse 对象。

例如,我可以像之前定义的那样定义我的库参数: library_name.name = ... library_name.help = ... library_name.type = str library_name.required = True

library_number.name = ...
library_number.help = ...
library_number.type = int
library_number.required = True 
...

但是我希望这个对象设置与用户想要的库一样多,所以我可以向这些选项添加一个附加操作,但用户必须以正确的顺序提供所有输入:

--library-name lib1 --library-number 1 --library-name lib2 --library-number 2

但这对用户来说并不容易,我所做的是:

--library "name=lib1;number=1" --library "name=lib2;number=2"

但这不是“漂亮”,我更喜欢这样的东西,但我仍然想检查这是否是正确的格式:

--library lib1 1 --library lib2 2

这更清楚吗?


我应该再解释一下,我更改了您给我的内容,以便用户可以--library library-name=test library-number=5,因此不需要提供所有字段,但是我希望其中一些是必需的,但要这样做,我需要知道一旦检查了所有参数是否已解决所需的参数

    class MiltipleParameters(object):
        def __init__(self, types):
            self.types = types
            self.index = None
            self.__name__ = "MiltipleParameters"
        def __call__(self, arg):
            parts = arg.split("=")
            if not self.types.has_key(parts[0]):
                raise argparse.ArgumentTypeError(parts[0] + " is an invalid flag! Available ones are: "+", ".join(self.types.keys()))
            try:
                value = self.types[parts[0]](parts[1])
            except:
                raise argparse.ArgumentTypeError("invalid " + self.types[parts[0]].__name__ + " value: '" + parts[1] + "' for sub parameter '" + parts[0] + "'")
            self.index = parts[0]
            return (parts[0], value)

这种类型采用带有 param_name:type 的哈希表,我可以添加必填字段以便对其进行检查。但我确实需要知道何时结束检查所需的参数是否设置在哪里。是否可以 ?

4

4 回答 4

1

您可以创建一个非常简单的状态机:

class NargsTypeChecker(object):
    def __init__(self, types):
        self.types = types
        self.index = 0
    def __repr__(self):
        return self.types[self.index].__name__
    def __call__(self, arg):
        value = self.types[self.index](arg)
        self.index = (self.index + 1) % len(self.types)
        return value

用作:

parser.add_argument('--library', nargs=3, type=NargsTypeChecker((int, float, str)))

还有一些错误输出:

$python3 complex_type.py --library lib 1 3.6
Namespace(library=['lib', 1, 3.6])
$python3 complex_type.py --library lib other 3.6
usage: complex_type.py [-h] [--library LIBRARY LIBRARY LIBRARY]
complex_type.py: error: argument --library: invalid int value: 'other'
$python3 complex_type.py --library lib 2 other
usage: complex_type.py [-h] [--library LIBRARY LIBRARY LIBRARY]
complex_type.py: error: argument --library: invalid float value: 'other'
于 2013-09-12T09:45:35.700 回答
0

如果您的库名称不包含空格,您可以简单地使用一个字符串,然后执行

library = argstring.split()

这将返回一个名称和编号library的列表。library[0]library[1]

于 2013-09-12T08:57:31.663 回答
0

如果您可以接受以下格式:--library lib1:1 --library lib2:2

def libType(ls):
    name, num = ls.split(':')
    return name, int(num)

parser.add_argument("--library", action = "append", type=libType)
# you get: Namespace(library=[('lib1', 1), ('lib2', 2)])

如果您更喜欢坚持使用:--library lib1 1 --library lib2 2

parser.add_argument("--library", action = "append", nargs=2)
# you get: Namespace(library=[['lib1', '1'], ['lib2', '2']])

然后你必须执行额外的类型检查才能得到 int 而不是 str。

于 2013-09-12T09:42:12.837 回答
0

另一个具有自定义操作的解决方案:

import argparse

class LibAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        try: 
            lib = {'name': values[0], 'type': int(values[1])}
            if namespace.library:
                namespace.library.append(lib)
            else:
                namespace.library=[lib]
        except ValueError:
             parser.error("Problem with library: %s is not int"%(values[1])) 

parser = argparse.ArgumentParser()
parser.add_argument("--library", action = LibAction, nargs=2)
args = parser.parse_args()
print args     

您获得:

Namespace(library=[{'type': 1, 'name': 'lib1'}, {'type': 2, 'name': 'lib2'}])

以及一些错误处理,如果你使用:--library libA a

于 2013-09-12T10:14:32.597 回答