【问题标题】:Case insensitive argparse choices不区分大小写的 argparse 选择
【发布时间】:2014-12-23 08:39:09
【问题描述】:

是否可以以不区分大小写的方式检查argparse choices

import argparse
choices = ["win64", "win32"]
parser = argparse.ArgumentParser()
parser.add_argument("-p", choices=choices)
print(parser.parse_args(["-p", "Win32"]))

结果:

usage: choices.py [-h] [-p {win64,win32}]
choices.py: error: argument -p: invalid choice: 'Win32' (choose from 'win64','win32')

【问题讨论】:

    标签: python argparse case-insensitive


    【解决方案1】:

    通过使用将参数转换为小写

    type = str.lower
    

    用于-p 开关。

    chepnercomment 中指出了此解决方案。我之前提出的解决方案是

    type = lambda s : s.lower()
    

    这也是有效的,但使用str.lower 更简单。

    【讨论】:

    • 您可以通过简单地使用type = str.lower 来摆脱lambda,因为str.lower 是一个接受字符串并以小写形式返回的函数。
    • 由于string.lower(s) 函数 已被弃用并替换为s.lower() 方法,我会推荐最初建议的lambda 方法。
    • @Mark 这两个版本都没有使用 string 模块中已弃用的函数。请注意,使用了str.lower(没有ing),这是str 类中的方法,将self 作为其唯一参数,这就是该技巧起作用的原因。
    • @5gon12eder 感谢您的提醒,这是有道理的!很高兴知道。 @chepner 的描述让我失望,因为他说这是 str.lower function ,它“接受一个字符串”,这意味着他指的是现在已弃用的 function 而不是不接受任何输入但作用于self 的替换方法
    • obj.method(*args, **kwargs) 大部分与type(obj).method(obj, *args, **kwargs) 相同。 str.lower 应该被正确地称为函数,因为它的任何参数都没有被绑定,而 obj.lower 是一个方法,因为 obj 被绑定为第一个参数。
    【解决方案2】:

    如果您不介意丢失案例信息,在type 中使用lower 是一种不错的方式。

    如果你想保留案例,你可以定义一个自定义的choices 类。 choices 需要两种方法,__contains__(用于测试 in)和迭代(用于列出选择)。

    class mylist(list):
        # list subclass that uses lower() when testing for 'in'
        def __contains__(self, other):
            return super(mylist,self).__contains__(other.lower())
    choices=mylist(['win64','win32'])
    parser = argparse.ArgumentParser()
    parser.add_argument("-p", choices=choices)
    print(parser.parse_args(["-p", "Win32"]))
    # Namespace(p='Win32')
    

    帮助是:

    usage: ipython [-h] [-p {win64,win32}]
    
    optional arguments:
      -h, --help        show this help message and exit
      -p {win64,win32}
    

    【讨论】:

    • 为了安全起见,我可能会使用choices = mylist(map(str.lower, ['win64', 'win32'])),或者覆盖__init__ 来执行此操作。
    【解决方案3】:

    使用单行也可以保留案例信息:

    type = lambda arg: {x.lower(): x for x in choices}[arg.lower()],
    

    其中的选择与传递给选择参数的列表相同。

    【讨论】:

      【解决方案4】:

      为了澄清@5gon12eder 的答案,您需要将“类型”作为另一个参数添加到add_argument

      parser.add_argument("-p", choices=choices, type=str.lower)
      

      这将确保输入是小写的。
      确保不要在lower 之后添加括号。

      【讨论】:

        猜你喜欢
        • 2019-11-12
        • 2014-05-24
        • 1970-01-01
        • 2011-05-16
        • 2014-05-22
        • 2015-11-10
        • 2021-10-19
        • 2021-08-27
        • 2013-10-28
        相关资源
        最近更新 更多