Я работаю над проектом командной строки, где у меня возникла проблема с обработкой подкоманды 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
Как я могу это исправить?






Возможно, вы неправильно понимаете, как определять аргументы. Вы, вероятно, предполагаете, что можете использовать аргументы в своем примере как позиционные аргументы в вызове функции, но анализатор аргументов работает иначе. Вот что происходит в вашем примере
python todo.py ./todo add " I am soham Das Biswas"
Вы определили два параметра: "./todo" и "o". Часть ./todo add присваивает значение add аргументу ./todo.
«Я сохам Дас Бисвас» не назначается на «о», потому что в призыве не упоминается «о». Если вы хотите присвоить что-то «о», вам нужно что-то вроде o value_i_want_to_assign.
Что вы хотите, чтобы ваш код делал?
Это дает мне x является обязательным, и я не хочу указывать его обязательным
Поэтому, когда я спрашиваю позицию x, она дает позицию, а когда я не хочу, она не дает обязательной
С
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 для обязательных вещей. Есть способы изменить это, но это усложняет понимание входных данных как для вас, так и для ваших пользователей.
Почему вы указываете
todoдважды?./todoбыло бы именем команды, если бы файл называлсяtodoвместоtodo.pyи был помещен в текущий каталог и помечен как исполняемый;python todo.py— это эквивалентная команда для запуска скрипта в файлеtodo.pyявно с использованием интерпретатораpython.