Как решить проблему командной строки с помощью python argparse?

Я работаю над проектом командной строки, где у меня возникла проблема с обработкой подкоманды add, как указано в комментариях ниже:

import argparse
import sys
def todo(args):
    if args.o =='add':
        print("Added Todo: "+args.x)
        f=open("todo.txt", "a+")
        c= str(count+1)
        p= '\n'+'. '+args.x
        f.write(p)
        f.close()
    elif args.o =='report':
        return 
    elif args.o =='del NUMBER':
        return 
    elif args.o =='done NUMBER':
        return 
    elif args.o =='help':
        print ("Usage :-"+
               "\n"+'$ ./todo add "todo item"           # add a new todo'+
               "\n"+'$ ./todo ls                        # Show remaining todos'+
               "\n"+'$ ./todo del NUMBER                # delete a todo'+
               "\n"+'$ ./todo done NUMBER               # complete a todo'+
               "\n"+'$ ./todo help                      # Show Usage'+
               "\n"+'$ ./todo report                    # Statistics')
    elif args.o =='ls':
        f=open("todo.txt", "r")
        print(f.read())
        f.close()
if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('./todo', type=str, default = "./todo")
    parser.add_argument('o', type=str, default = "add")
    args = parser.parse_args()
    if args.o =='add':                     # <- starting here
        parser.add_argument('x', type=str, default=None)
        args = parser.parse_args()
        sys.stdout.write(str(todo(args)))  # <- ending here
    else:
        a = parser.parse_args()
        sys.stdout.write(str(todo(args)))

Когда я запускаю этот скрипт в Powershell, я получаю какую-то ошибку, например

PS E:\python projects\fellowship challenge\python> python todo.py ./todo add " I am soham Das Biswas"
usage: todo.py [-h] ./todo o
todo.py: error: unrecognized arguments:  I am soham Das Biswas

Как я могу это исправить?

Почему вы указываете todo дважды? ./todo было бы именем команды, если бы файл назывался todo вместо todo.py и был помещен в текущий каталог и помечен как исполняемый; python todo.py — это эквивалентная команда для запуска скрипта в файле todo.py явно с использованием интерпретатора python.

tripleee 16.12.2020 19:24
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
614
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

python todo.py ./todo add " I am soham Das Biswas"

Вы определили два параметра: "./todo" и "o". Часть ./todo add присваивает значение add аргументу ./todo.

«Я сохам Дас Бисвас» не назначается на «о», потому что в призыве не упоминается «о». Если вы хотите присвоить что-то «о», вам нужно что-то вроде o value_i_want_to_assign.

Что вы хотите, чтобы ваш код делал?

Это дает мне x является обязательным, и я не хочу указывать его обязательным

SDB PROGRAM LEARNER 16.12.2020 19:20

Поэтому, когда я спрашиваю позицию x, она дает позицию, а когда я не хочу, она не дает обязательной

SDB PROGRAM LEARNER 16.12.2020 19:22
Ответ принят как подходящий

С

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('./todo', type=str, default = "./todo")
parser.add_argument('o', type=str, default = "add")
args = parser.parse_args()
print(args)

некоторые примеры запусков:

1301:~/mypy$ python3 stack65328753.py -h
usage: stack65328753.py [-h] ./todo o

positional arguments:
  ./todo
  o

optional arguments:
  -h, --help  show this help message and exit

С 2 струнами:

1303:~/mypy$ python3 stack65328753.py todo add
Namespace(o='add', **{'./todo': 'todo'})

с доп.:

1304:~/mypy$ python3 stack65328753.py todo add "extra string"
usage: stack65328753.py [-h] ./todo o
stack65328753.py: error: unrecognized arguments: extra string

Это определяет 2 аргумента, оба positionals. Они идентифицируются по положению, а не по какой-либо строке «флаг». Первая строка присваивается атрибуту «./todo» args, а вторая — «o». Нечего брать третью струну.

Вы можете получить доступ ко второму значению с помощью args.o, но args../todo не работает. Вместо этого вам придется getattr(args, "./todo"). Так что использование такого «причудливого» имени обычно не является хорошей идеей.

Поскольку это обязательные позиционные обозначения, нет смысла указывать default.

Измените аргументы на optionals:

parser = argparse.ArgumentParser()
parser.add_argument("--dir", default = "./todo")
parser.add_argument('-o', type=str, default = "add")
args = parser.parse_args()
print(args)
print(args.dir, args.o)

и работает:

1315:~/mypy$ python3 stack65328753.py -h
usage: stack65328753.py [-h] [--dir DIR] [-o O]

optional arguments:
  -h, --help  show this help message and exit
  --dir DIR
  -o O

1316:~/mypy$ python3 stack65328753.py
Namespace(dir='./todo', o='add')
./todo add

1316:~/mypy$ python3 stack65328753.py --dir ./mydir 
Namespace(dir='./mydir', o='add')
./mydir add

1316:~/mypy$ python3 stack65328753.py --dir ./mydir -o subtract
Namespace(dir='./mydir', o='subtract')
./mydir subtract

1316:~/mypy$ python3 stack65328753.py --dir ./mydir -o "an extra string"
Namespace(dir='./mydir', o='an extra string')
./mydir an extra string

Вы пытаетесь добавить аргумент «x» на основе значения args.o

args = parser.parse_args()
if args.o =='add':                     # <- starting here
    parser.add_argument('x', type=str, default=None)
    args = parser.parse_args()

Но первый parse_args() выдает нераспознанную ошибку и завершает работу. Так вы никогда не пойдете на это дополнение.

parser = argparse.ArgumentParser()
parser.add_argument("--dir", default = "./todo")
parser.add_argument('-o', type=str, default = "add")
args, extras = parser.parse_known_args()
print(args, extras)
print(args.dir, args.o)

if args.o == "add":
    parser.add_argument('x')
    args = parser.parse_args()
    print(args)

Справка не меняется, потому что на это действует первая parse:

1318:~/mypy$ python3 stack65328753.py -h
usage: stack65328753.py [-h] [--dir DIR] [-o O]

optional arguments:
  -h, --help  show this help message and exit
  --dir DIR
  -o O


1323:~/mypy$ python3 stack65328753.py --dir ./mydir -o "an extra string"
Namespace(dir='./mydir', o='an extra string') []
./mydir an extra string

parse_known_args помещает дополнительную строку в extras. Теперь он добавляет аргумент x:

1323:~/mypy$ python3 stack65328753.py --dir ./mydir -o add "an extra string"
Namespace(dir='./mydir', o='add') ['an extra string']
./mydir add
Namespace(dir='./mydir', o='add', x='an extra string')

Альтернативой было бы просто

args.x = extras

который будет (возможно, пустым) списком.

С такой проблемой я настоятельно рекомендую использовать этот print(args), чтобы посмотреть, что делает парсер. И отладьте синтаксический анализатор, прежде чем встраивать его в более крупный скрипт. И для начала не пытайтесь быть слишком фантазией. Используйте optionals для опциональных, необязательных вещей и positionals для обязательных вещей. Есть способы изменить это, но это усложняет понимание входных данных как для вас, так и для ваших пользователей.

Другие вопросы по теме