【问题标题】:argparse - Different mandatory / available parameters per actionargparse - 每个操作不同的强制/可用参数
【发布时间】:2016-11-08 13:45:44
【问题描述】:

我正在寻找具有以下结构的参数解析器:

options [ 'backup', 'consistency_check', 'backup_and_consistency_check']

--database [ required ]
--action [ required choice from list options ]
  --where_to_backup_to [ only required if --action is 'backup' ]
  --what_file_to_consistency_check [ only required if --action is 'consistency_check']
--clean [ optional ]
  --force [ optional if --clean is also in arguments ]

如何使用 ArgumentParser 模块实现可选参数,具体取决于作为另一个命令行参数所做的选择。

如果例如命令行参数是,我希望使 ArgParse 失败

--d database_name --a backup --what_file_to_consistency_check /var/tmp/file.bak

这是我到目前为止所得到的(我知道它很少,但如果我从一开始就没有正确地使用子解析器,我不想在完全错误的方向上走)

actions = ['backup', 'consistency_check', 'backup_and_consistency_check']

def create_parser():
    parser = ArgumentParser(description='Parser for Backup / Consistency Check')

    parser.add_argument('--database', '-d', dest='db', help='Database name', choices=get_active_database_list())

    parser.add_argument('--action', '-a', dest='action', help='Action option', choices=actions)
    # --where_to_backup_to [ only if action = backup ]
    # --what_file_to_consistency_check [ only if action = cc ]
    parser.add_argument('--clean', '-c', dest='clean', help='Clean')
    # --force [ only available if --clean is also in arguments ]

    return parser

【问题讨论】:

  • 为每个动作提供自己的子解析器。顺便说一句,按照惯例,您会将操作作为位置参数。
  • 你能举个例子吗?它甚至不必是实际代码 - 只是一个描述?我可以将子解析器添加到特定参数而不是整个解析器吗?
  • 以动作为条件是子解析器的适用于,因此文档中的示例都适用。
  • 将再看一遍文档 - 这是令人难以置信的东西!
  • 我试图让标题更能描述实际的问题——“Python Argument Parsing”可以表示任何数量的东西,问题标题的部分目标是足够描述其他有相同问题的人实际上可以确定给定问题(希望有答案)是否真的正在解决他们遇到的相同问题。

标签: python arguments command-line-arguments argparse


【解决方案1】:

我认为使用动态选项解析器将动作作为位置参数是一个不错的选择:

if __name__ == "__main__":

    action = sys.argv[1]

    parser = create_parser(action)
    args = parser.parse_args()

【讨论】:

  • argparse 内置了对子命令的支持——使用它,你的--help 涵盖了所有可能性,而不是试图自己破解类似的东西。此外,这样您可以在参数之前拥有选项。
  • 您好,感谢您的回复。我试图避免使用不必要的 if 条件和从参数中提取变量等,因为这些选项还包括另一个类似的功能 - 我已经使用新的 --clean 选项更新了代码,然后还允许使用可选的 --force (强制清理)——是的,在查尔斯所说的基础上,ArgParse 足够聪明,可以施展魔法,所以我想充分利用它的潜力 :)
【解决方案2】:

执行此操作的常规方法如下所示:

def create_parser():
    parser = ArgumentParser(description='Parser for Backup / Consistency Check')

    parser.add_argument('--database', '-d', dest='db', help='Database name', choices=get_active_database_list())
    parser.add_argument('--timeout', '-t', dest='timeout', help='Timeout limit (in minutes)')

    subparsers = parser.add_subparsers()

    parser_backup = subparsers.add_parser('backup', help='Run a backup')
    parser_backup.set_defaults(action='backup') # or even pass the backup function itself, vs a string
    parser_backup.add_argument('dest', help='Where to backup to') # where to backup to

    parser_check = subparsers.add_parser('consistency_check', help='Run a consistency check')
    parser_check.set_defaults(action='consistency_check')
    parser_check.add_argument('source', help='What file to check for consistency')

    return parser

...用法为:

# here, action='backup' and dest='/path/to/dest'
yourtool -d db -t 15 backup /path/to/dest

...或...

# here, action='consistency_check' and source='/path/to/content/to/check'
yourtool -d db -t 15 consistency_check /path/to/content/to/check

【讨论】:

  • 谢谢,这实际上解决了很多问题。通过添加一个子解析器,这就像添加另一个参数一样,除了这个参数也有可选参数。我很困惑,以为我会添加一个子解析器,然后将备份作为参数添加到子解析器。但是备份是子解析器!
  • 如果add_subparsers(dest='action') 你不需要set_defaults 语句(除非你想设置一个函数值)。
【解决方案3】:

如果目前子解析器看起来太复杂,我认为没有它们你仍然可以获得有用的解析器:

def create_parser():
    parser = ArgumentParser(description='Parser for Backup / Consistency Check')

    parser.add_argument('--database', '-d', dest='db', help='Database name', choices=get_active_database_list())

    parser.add_argument('--action', '-a', help='Action option', choices=actions)
    parser.add_argument('target', help='target for backup or check')
    parser.add_argument('--clean', '-c', help='Clean') # default dest is 'clean'
    parser.add_argument('--force', help='force clean')
    return parser

如果需要database,您可能需要向其添加required=True 参数。或者让它成为一个位置。否则考虑如果用户不提供它你会怎么做。 IE。如果args.db is None?有可以使用的默认数据库吗?

看起来所有的操作选择都需要一个文件或目录参数——备份或检查的目标。用户将其称为“--where_to_backup_to”还是“--what_file_to_consistency_check”是否重要?通过在这里使用位置,我要求他们给出某种名称,但您可以根据“动作”来解释它。

看起来force 只是clean 的更强版本。如果用户指定--force 而不是--clean,您认为用户想要什么?在这里,我接受两者并让您的代码选择最有意义的。

我的理念是解析器的主要目标是弄清楚用户想要什么。错误检查在防止输入不明确时最有用。但不应该挑剔。一个简单的解析器设计通常比一个过于复杂的解析器设计要好。

【讨论】:

    猜你喜欢
    • 2014-04-15
    • 2012-08-14
    • 2018-04-29
    • 2021-09-07
    • 2015-06-16
    • 2021-03-07
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    相关资源
    最近更新 更多