简体   繁体   English

Python Argparse,如何正确组织ArgParse代码

[英]Python Argparse, How to Properly Organize ArgParse Code

I haven't used argparse in 10 years, but I understand it and what I have below does work as I want it to work... but this is going to get a lot more complicated as I continue adding commands, parsers and subparsers. 我已经有10年没有使用argparse了,但是我理解它,并且下面的内容确实可以正常工作……但是随着我继续添加命令,解析器和子解析器,这将变得更加复杂。 I'm wondering what the best way is to organize this? 我想知道最好的组织方式是什么? In my mind I should be able to see the command sequence in the text nearly as clearly as I see it in my diagram... but everytime I look at it, after being away for a while, my brain swims as I try to follow it. 在我的脑海中,我应该能够像在图表中一样清晰地看到文本中的命令序列...但是,每次我查看它时,只要走了一会儿,我的脑子都会游动,因为我试图跟随它它。 There has to be a better way to organize this right? 必须有更好的方法来组织这项权利吗? 在此处输入图片说明

import argparse
from modules import cli_tools

#LVL 1: create the top-level parser for the "sacs" command.
sacs_parser = argparse.ArgumentParser(prog = 'sacs', description = 'Master Command For Controlling SACS.')
sacs_subparsers = sacs_parser.add_subparsers(help='Management Module Selector.')

#LVL 2: create the second-level parsers for the "sacs [module]" commands.
csv_parser = sacs_subparsers.add_parser('csv', help='Generic CSV Management Module.')
am_parser = sacs_subparsers.add_parser('am', help='SACS Asset Management Module.')
mm_parser = sacs_subparsers.add_parser('mm', help='SACS Metric Management Module.')

#LVL 3: create the third-level subparser for the "sacs [module] [action]" commands.
csv_action_subparser = csv_parser.add_subparsers(help='The action to perform.')
mm_action_subparser = mm_parser.add_subparsers(help='The action to perform.')

#LVL 4: create the fourth-level subparser for the "sacs [module] [action] [type]" commands.
mm_create_parser = mm_action_subparser.add_parser('create', help='Used to Create a new event/asset input file.')
mm_create_type_parser = mm_create_parser.add_subparsers(help='The type of file to create.')

#LVL 5: create the fifth-level parser for the "sacs [module] [action] [type]" commands.
csv_reconcile_parser = csv_action_subparser.add_parser('reconcile', help='reconcile two csvs.')
mm_create_asset_parser = mm_create_type_parser.add_parser('assets', help='Create an Asset File.')
mm_create_asset_subtype_parser = mm_create_asset_parser.add_subparsers(help='The type of file to create.')
mm_create_event_parser = mm_create_type_parser.add_parser('events', help='Create an Event File.')

#LVL 6: create the sixth-level parser for the "sacs [module] [action] [type] [subtype]" commands.
mm_create_asset_uaid_parser = mm_create_asset_subtype_parser.add_parser('uaid', help='Create an Asset File with UAID as the primary key.')
mm_create_asset_vid_parser = mm_create_asset_subtype_parser.add_parser('vid', help='Create an Asset File with Vulnerability ID as the primary key.')

#COMMAND ARGS: Add Arguments to the final command "sacs csv reconcile [args]"
csv_reconcile_parser.add_argument('key', help='The name of the field that holds the unique ID to compare against.')
csv_reconcile_parser.add_argument('inputfile1', help='The master file (used when same record exists in both files).')
csv_reconcile_parser.add_argument('inputfile2', help='The secondary file, which is trumped by the master file.')
csv_reconcile_parser.add_argument('outputfile', help='The output file; note it will be overwritten if it exists.')
csv_reconcile_parser.set_defaults(func=cli_tools.csv_reconcile)

#COMMAND ARGS: Add Arguments to the final command "sacs mm create assets uaid [args]"
mm_create_asset_uaid_parser.add_argument('appmapp_file', help='The input file.')
mm_create_asset_uaid_parser.add_argument('output_file', help='The output file.')
mm_create_asset_uaid_parser.set_defaults(func=cli_tools.asset_create_uaid)

#COMMAND ARGS: Add Arguments to the final command "sacs mm create assets vid [args]"
mm_create_asset_vid_parser.add_argument('vulnerability_file', help='The input file.')
mm_create_asset_vid_parser.add_argument('appmapp_file', help='The output file.')
mm_create_asset_vid_parser.add_argument('output_file', help='The output file.')
mm_create_asset_vid_parser.set_defaults(func=cli_tools.asset_create_vid)

args = sacs_parser.parse_args()
args.func(args)

Potential avenues to better way: 更好的方法的潜在途径:

  1. parser/subparser renaming. 解析器/子解析器重命名。
  2. change the ordering of the statements. 更改语句的顺序。
  3. some way to indent without messing with python. 缩进而不弄乱python的某种方法。

All ideas are on the table, I want to see how others deal with this while designing complex commands. 所有想法都摆在桌面上,我想看看其他人在设计复杂命令时如何处理。

The usual way of adding clarity to Python code is to package steps in functions and even classes. 提高Python代码清晰度的通常方法是将步骤封装在函数甚至类中。 argparse itself is a set of classes. argparse本身是一组类。 Each of your parsers (including subparsers) are argparse.ArgumentParser objects. 您的每个解析器(包括子解析器)都是argparse.ArgumentParser对象。 Each add_argument creates an argparse.Action subclass object. 每个add_argument创建一个argparse.Action子类对象。 The add_subparsers creates (and returns) a specialized Action subclass that handles subparsers. add_subparsers创建(并返回)处理子解析器的专用Action子类。 And finally parse_args returns an argparse.Namespace object. 最后, parse_args返回argparse.Namespace对象。

Whether any of that is applicable in your case, I don't know. 我不知道这是否适用于您的情况。 Your code is readable, so I easily get an idea of what you are doing. 您的代码可读,因此我可以轻松了解您的操作。 I've never seen anyone use so many levels of subparsers. 我从未见过有人使用这么多级别的子解析器。 In fact using more than one level is something of a novelty (judging from some earlier SO questions). 实际上,使用多个级别是新颖的(从一些早期的SO问题判断)。

I like to stress that the first job of argparse is to figure out what your user wants. 我想强调, argparse的第一项工作就是弄清楚您的用户想要什么。 The parsing is the first priority. 解析是第一要务。 Secondly it should make it easy to express what they want. 其次,它应该使表达他们想要的东西变得容易。 I wonder whether this multilevel subparsing is easy to use. 我想知道这种多级细分是否易于使用。 The way that argparse splits the help among subparsers makes it hard to display an big overview. argparse在子解析器之间分配help的方式使得很难显示出大的概览。

At some point big packages start to write their own helps, and even customize the parser to suit their needs. 在某些时候,大型程序包开始编写自己的帮助,甚至自定义解析器以适合其需求。

You might get a better answer on CodeReview . 您可能会在CodeReview上得到更好的答案。 The regulars there seem to more interested in code organization and naming issues. 那里的常客似乎对代码组织和命名问题更感兴趣。 SO is more oriented to problem solving. SO更着重于解决问题。 I discourage referrals to CR if the topic is too specialized, but this is more of a general Python question than an argparse specific one. 如果主题过于专业化,我不建议转用CR,但这更多的是Python的一般问题,而不是argparse特定问题。 But read up on what CR expects in a question. 但是,请仔细阅读CR在问题中的期望。

Multiple level argparse subparsers 多级argparse子解析器

Argparse with required subparser 带有所需子解析器的Argparse

argparse subparser monolithic help output argparse次解析器整体帮助输出

Python argparser repeat subparse Python argparser重复子解析

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM