使用argparse

时间:2016-05-30 22:27:17

标签: python argparse

我正在编写一个python命令行客户端程序来与api连接。用户使用客户端程序运行以下命令,客户端程序对api

进行以下示例调用
  

python run.py --car - >调用方法get_all(vehicle_type)请求 - > / car / all - <返回所有汽车列表

     

python run.py --van - > / van / all - >返回所有货车的清单

     

/ car / id / 123 - > - >调用方法get_by_id(vehicle_type,id)请求 - >返回ID为123的汽车列表

与其他所有人相似。

  

/ car / color / red红色车的返回列表

     

/ car / model_no / 31x使用model_no 31x返回汽车

     

/ van / id / 312返回id为321的货车列表

我正在为此目的使用arg解析并且无法正确地执行此操作。现在,我在做。

parser = argparse.ArgumentParser()
grp1 = parser.add_mutually_exclusive_group(required=True)
grp2 = parser.add_mutually_exclusive_group()

grp1.add_argument('--car', action='store_const', const='car')
grp1.add_argument('--van', action='store_const', const='van')

grp2.add_argument('--id', help='get by id')
grp2.add_argument('--model_no', help='get by model number')
grp2.add_argument('--color', help='get by color') 

arg_dict = {k:v for k, v in vars(args).items() if v}

当我为命令运行此代码时。

  

python run.py --car --id 123

我得到了

  

{'车' :' car' ,' id' :' 123'}

我循环遍历此dict并使用getattr通过键名称调用函数' get_by_ {name}' .format(name = key)。 但是,我的代码看起来并不好看,因为我必须检查长度是否为1,然后调用get all function并检查车辆类型。有没有更好的方法来正确使用argparse来使代码更紧凑。

2 个答案:

答案 0 :(得分:2)

一个相对直接的做你想要的方式(我认为)是:

arg_dict = {k:v for k, v in vars(args).items() if v}

您可以使用if args.id: ... if hasattr(args,'id'): ... 与[{1}}保持一致(就像您对if get(vars,'id',None): ... 所做的那样。但是更容易测试

args

大于

locals()

argparse

如果您真的想从registries值生成函数名,可以进行字典查找(parser.register或自定义词典)。内部fn = locals().get('get_by_%s'%'id') fn(args.vehicle_type, args.id) 通过argparse使用parser.set_defaults字典。

args

const文档显示如何使用getby_group.add_argument('--id',dest='fn',action='store_const', const=get_by_id) args.fn(...) 属性定义为函数。但是这种特殊用途仅适用于subparsers。

您可以使用get_by_id设置功能,例如

store_const

然后

fn

将运行value函数。

<删除了使用此class GetAction(argparse._StoreAction): # barest customization def __init__(self, *args, **kwargs): fn=kwargs.pop('fn') super(GetAction, self).__init__(*args, **kwargs) self.fn = fn def __call__(self, parser, namespace, values, option_string=None): super(GetAction, self).__call__(parser, namespace, values, option_string=None) setattr(namespace, 'fn', self.fn) parser.set_defaults(fn=get_all) # default action getby_group.add_argument('--id', dest='value', action=GetAction, fn=get_by_id) getby_group.add_argument('--color',dest='value', action=GetAction, fn=get_by_color) getby_group.add_argument('--model',dest='value', action=GetAction, fn=get_by_model) args = parser.parse_args() args.fn(args.vehicle_type, args.value) 的版本。接受价值时遇到了问题;设置编辑历史记录以获取详细信息>

===================

以下是定义if-else属性和spriteCircle.body.damping = 0.9;

的自定义操作方法
0

但是 - 请注意,类定义需要比1树更多的代码行。并且花了我更长的时间来写作。

答案 1 :(得分:1)

我发现在使用mutual_exclusive_groups时我经常使用dest option,因此你有一个带有动态值的变量:

DimCities[ExitCity]

然后对于第二组,您可以在指定选项时使用import argparse parser = argparse.ArgumentParser() grp1 = parser.add_mutually_exclusive_group(required=True) grp2 = parser.add_mutually_exclusive_group() group_1_options = {"action":"store_const",'dest':"vehicle"} grp1.add_argument('--car', const="car", **group_1_options) grp1.add_argument('--van', const='van', **group_1_options) 应用更改,以便保存对指定选项文本的引用:

type

然后可以检索请求,如:

parser.set_defaults(request=("get_all",None))

request_args = {"id":'get by id',
                "model_no":"get by model number",
                "color":"get by color"}

grp2 = parser.add_mutually_exclusive_group()
for arg_name, help_text in request_args.items():
    grp2.add_argument("--"+arg_name, help=help_text, dest="request",
                      type=(lambda x, arg_text=arg_name:(arg_text,x)))

然后您可以保证只需处理def test(argline): namespace = parser.parse_args(argline.split()) kind,value = namespace.request print(namespace.vehicle, kind, value) vehicle选项:

request