Argparse: Требуемый аргумент 'y', если присутствует 'x' - программирование
Подтвердить что ты не робот

Argparse: Требуемый аргумент 'y', если присутствует 'x'

У меня есть следующее требование:

./xyifier --prox --lport lport --rport rport

для аргумента prox, я использую action = 'store_true', чтобы проверить, присутствует ли он или нет. Я не требую никаких аргументов. Но, если --prox установлен, мне также нужны rport и lport. Есть ли простой способ сделать это с помощью argparse без написания условного условного кодирования.

Подробнее Код:

non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', type=int, help='Listen Port.')
non_int.add_argument('--rport', type=int, help='Proxy port.')
4b9b3361

Ответ 1

Нет, в argparse нет никакой опции для создания взаимоисключающих наборов параметров.

Самый простой способ справиться с этим:

if args.prox and args.lport is None and args.rport is None:
    parser.error("--prox requires --lport and --rport.")

Ответ 2

Вы говорите о наличии условно необходимых аргументов. Подобно @borntyping, вы можете проверить наличие ошибки и сделать parser.error(), или вы можете просто применить требование, связанное с --prox, когда вы добавляете новый аргумент.

Простым решением для вашего примера может быть:

non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', required='--prox' in sys.argv, type=int)
non_int.add_argument('--rport', required='--prox' in sys.argv, type=int)

Таким образом required получает либо True, либо False в зависимости от того, используется ли пользователь --prox. Это также гарантирует, что -lport и -rport имеют независимое поведение между собой.

Ответ 3

Используете ли вы lport, когда prox не установлен. Если нет, почему бы не сделать аргументы lport и rport prox? например.

parser.add_argument('--prox', nargs=2, type=int, help='Prox: listen and proxy ports')

Это экономит ваши пользователи. Так же легко проверить if args.prox is not None: как if args.prox:.

Ответ 4

Как насчет использования метода parser.parse_known_args(), а затем добавьте аргументы --lport и --rport в качестве требуемых аргументов, если --prox присутствует.

# just add --prox arg now
non_int = argparse.ArgumentParser(description="stackoverflow question", 
                                  usage="%(prog)s [-h] [--prox --lport port --rport port]")
non_int.add_argument('--prox', action='store_true', 
                     help='Flag to turn on proxy, requires additional args lport and rport')
opts, rem_args = non_int.parse_known_args()
if opts.prox:
    non_int.add_argument('--lport', required=True, type=int, help='Listen Port.')
    non_int.add_argument('--rport', required=True, type=int, help='Proxy port.')
    # use options and namespace from first parsing
    non_int.parse_args(rem_args, namespace = opts)

Также имейте в виду, что вы можете предоставить пространство имен opts, сгенерированное после первого синтаксического анализа, при повторном анализе остальных аргументов. Таким образом, в конце концов, после всего разбора, у вас будет одно пространство имен со всеми параметрами.

Недостатки:

  • Если --prox нет, другие два зависимых параметра даже не присутствуют в пространстве имен. Хотя на основе вашего прецедента, если --prox нет, то что происходит с другими параметрами, не имеет значения.
  • Необходимо изменить сообщение об использовании, поскольку парсер не знает полную структуру.
  • --lport и --rport не отображаются в справочном сообщении