【问题标题】:OptionParser: show extra information and allow for unspecified actionsOptionParser:显示额外信息并允许未指定的操作
【发布时间】:2013-11-30 21:59:02
【问题描述】:

(标题应为OptionParser: show extra help,但标题中不允许出现help字样)

我有这个OptionParser

parser = OptionParser(
    usage='usage: %s [options]' % (args[0]),
    version='%s Version %s' % (args[0], version))

parser.add_option('-a', '--action', choices=['menu'] , help='Allowed actions are: menu, and any menu action', default='menu')
parser.add_option('-1', '--file1',  type='string', help='First file')
parser.add_option('-2', '--file2',  type='string', help='Second file')
parser.add_option('--debug', action='store_true', help='run in debug mode')

--help 打电话给我:

Usage: /home/gonvaled/projects/bin/process_json.py [options]

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -a ACTION, --action=ACTION
                        Allowed actions are: menu, and any menu action
  -1 FILE1, --file1=FILE1
                        First file
  -2 FILE2, --file2=FILE2
                        Second file
  --debug               run in debug mode

这很好,但是缺少操作。问题是某些动作是在Menu 对象(我的实现)中定义的,只能通过执行来显示:

menu.showCommands()

也就是说,这些操作不是为OptionParser 定义的,但仍然可以通过命令行访问,因为除menu 之外的任何操作都将透明地传递给要处理的Menu 对象。因此,OptionParser 提供的帮助不知道这些操作。

如何告诉OptionParser 对象在显示帮助文本时,必须添加一些外部信息?在最后添加就足够了。我查看了docs,但似乎没有这样的选项。

编辑

实际运行我的程序表明,不仅缺少帮助。更糟糕的是:optparse 抱怨未知行为:

gonvaled@pegasus ~ » process_json.py -a prettyfy-from-obj
Usage: /home/gonvaled/projects/bin/process_json.py [options]

process_json.py: error: option -a: invalid choice: 'prettyfy-from-obj' (choose from 'menu')

我如何告诉optparse 接受action 的未指定值?

【问题讨论】:

    标签: python command-line-arguments optparse


    【解决方案1】:

    您发送给choices 参数的列表必须是该选项允许的所有可能参数的详尽列表。如果列表是['menu'],那么唯一允许的值是menu。这解释了您遇到的错误。

    注意the optparse module is deprecated,你应该使用argparse

    更简单的解决方案

    不要使用choices 并在之后验证参数。

    parser.add_option('-a', '--action', help='Allowed actions are: menu, and any menu action', default='menu')
    #...
    options, args = parser.parse_args()
    
    if options.action not in menu.showCommands():
        parser.error('Invalid action specified: %s' % options.action)
    

    或者,如果您不能这样做,如果您使用调用menu.call(action, params) 的操作并引发UnavailableAction 异常:

    parser.add_option('-a', '--action', help='Allowed actions are: menu, and any menu action', default='menu')
    #...
    options, args = parser.parse_args()
    # do something as normal
    try:
        menu.call(options.action, params)
    except UnavailableAction:
        print "Incorrect option" # (1)
        # crash appropriately
    

    如果解析器对象可用,您可以将(1) 更改为以下内容:

    parser.error('Invalid action specified: %s' % options.action)
    

    注意:这完全违背了使用choices 的目的,但如果您无法在解析 CLI 选项的函数/方法/模块范围内进行验证,则可以适用。


    此问题的任何其他解决方案取决于您自省 menu 对象以获取可用操作列表的能力。


    使用选择

    假设menu.showCommands 只是提供了可用命令的字符串列表,我的第一个猜测是:

    menu_choices = menu.showCommands().split()
    menu_choices.append('menu')
    parser.add_option('-a', '--action', choices=menu_choices , help='Allowed actions are: menu, and any menu action', default='menu')
    

    如果无法获取该格式的操作列表,您可能必须“解析”menu.showCommands 的输出

    使用回调

    您也可以将其实现为-a 选项的回调:

    def menu_option(option, opt_str, value, parser):
        if not value not in menu.showCommands().split():
            raise OptionValueError('Invalid action for menu')
    
    parser.add_option('-a', '--action', action='callback', callback=menu_option, help='Allowed actions are: menu, and any menu action', default='menu')
    

    这个选项更灵活一些。例如,如果您使用名为 has_action(menu, string) 的函数来检查 menuobject 是否有可用的 string 操作,您可以这样做:

    def menu_option(option, opt_str, value, parser):
        if not has_action(menu, value):
            raise OptionValueError('Invalid action specified for menu: %s' % value)
    

    更复杂的解决方案

    可能有很多更复杂的解决方案。一些想法(可能或 - 更有可能 - 不起作用)是:

    • 子类化 OptionParser 并创建您自己的具有您需要的东西(这样选择就没有效果)
    • 如果menu 有自己的OptionParser,则使用回调链式加载它
    • 如果menu 有自己的子解析器,have argparse use it directly

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-12
      • 1970-01-01
      • 2017-01-07
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多