Использование argparse.subparser с логическими значениями - PullRequest
1 голос
/ 17 февраля 2020

Я прочитал Python argparse документацию несколько раз и, должно быть, упустил что-то огромное. Я пытаюсь добавить синтаксис, похожий на make-файл, в мой инструмент cli, но, несмотря на флаг --help, показывающий мне ожидаемое поведение, ошибки при его выполнении:

test.py

import argparse
import os

def main():
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers()

    make_subparser = subparsers.add_parser("make")
    make_subparser.add_argument("update", action="store_false", help="Runs all make targets")
    make_subparser.add_argument("clean", action="store_false", help="Cleans up everything done previously")

    args = parser.parse_args()

    if args.update:
        os.system("touch test.txt")

    elif args.clean:
        os.system("rm test.txt")

    else:
        print("Bad args, see: python test.py make --help.")


if __name__ == "__main__":
    main()

Затем в моем терминале:

$> python test.py make --help
usage: test.py make [-h]

positional arguments:
  update      Runs all make targets

$> python test.py make update
usage: test.py [-h] {make} ...
test.py: error: unrecognized arguments: update
$> # this should make a file
$> 
$> python test.py make clean
usage: test.py [-h] {make} ...
test.py: error: unrecognized arguments: clean
$> # this should delete the file

Это прекрасно работает, если я поменяю action="store_false" на action="store_true", но есть дюжина команд make, поэтому я хочу только запустить тот, который пользователь добавляет в cli, если он пытается войти, он должен завершиться.

Ответы [ 2 ]

1 голос
/ 17 февраля 2020

Вместо отдельных логических флагов используйте один аргумент target, который допускает ограниченный набор значений.

make_subparser.add_argument("target", choices=['update', 'clean'], help="Runs all make targets")

if args.target == "update":
    ...
elif args.target == "clean":
    ...

Нет else, так как любая попытка передать что-то отличное от update или clean вызовет ошибку в parse_args, прежде чем args.target когда-либо будет установлен.

1 голос
/ 17 февраля 2020

В мире POSIX (и смежных с POSIX) логические аргументы обрабатываются как flags , которые передаются через командную строку как --argument. То, что вы хотите, это не логические аргументы (и это не то, как Make обрабатывает их тоже), это просто переменное число позиционных аргументов , то есть arity *:

make_subparser.add_argument('targets', nargs='*')

Это было бы ближе к тому, как работает Make. Тем не менее, из вашей командной строки это больше похоже на то, что вы на самом деле хотите вложить подкоманды .

...