Варианты argparse без учета регистра

Можно ли проверить выбор аргументов без учета регистра?

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')

person Peter    schedule 23.12.2014    source источник


Ответы (3)


Преобразуйте аргумент в нижний регистр, используя

type = str.lower

для переключателя -p.

На это решение указал chepner в комментарий. Решение, которое я предложил ранее, было

type = lambda s : s.lower()

что также допустимо, но проще просто использовать str.lower.

person 5gon12eder    schedule 23.12.2014
comment
Вы можете избавиться от лямбды, просто используя type = str.lower, поскольку str.lower — это функция, которая принимает строку и возвращает ее в нижнем регистре. - person chepner; 24.12.2014
comment
Поскольку функция string.lower(s) устарел и заменен на s.lower() method, я бы рекомендовал лямбда-подход, предложенный изначально. - person Mark; 14.03.2017
comment
@Mark Ни одна из версий не использует устаревшую функцию из модуля string. Обратите внимание, что используется str.lower (без ing), который является методом из класса str, принимающим self в качестве единственного параметра, поэтому трюк работает. - person 5gon12eder; 16.03.2017
comment
@ 5gon12eder Спасибо за предупреждение, это имеет смысл! Хорошо знать. Описание @chepner сбило меня с толку, потому что он сказал, что это функция str.lower, которая принимает строку, из которой следует, что он имел в виду ныне устаревшую функцию, а не замену метод, который не принимает никаких входных данных, но действует на self. - person Mark; 17.03.2017
comment
obj.method(*args, **kwargs) по большей части идентичен type(obj).method(obj, *args, **kwargs). str.lower следует правильно называть функцией, потому что ни один из ее аргументов не связан, тогда как obj.lower является методом, потому что obj связан в качестве первого аргумента. - person BallpointBen; 05.09.2018

Использование lower в type - хороший способ сделать это, если вы не возражаете против потери информации о деле.

Если вы хотите сохранить случай, вы можете определить собственный класс 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}
person hpaulj    schedule 23.12.2014
comment
На всякий случай я бы, вероятно, сделал choices = mylist(map(str.lower, ['win64', 'win32'])) или переопределил __init__, чтобы сделать это. - person BallpointBen; 05.09.2018

Сохранение информации о деле также возможно с помощью одного вкладыша:

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

Где варианты выбора будут тем же списком, который передается параметру выбора.

person Andreas Walter    schedule 31.10.2018