如何使用 python argparse 解决命令行问题?
How to solve command line problem using 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
我该如何解决这个问题?
您可能误解了如何定义参数。您可能假设您可以在示例中使用参数作为函数调用中的位置参数,但这不是参数解析器的工作方式。这是您的示例中发生的情况
python todo.py ./todo add " I am soham Das Biswas"
您定义了两个参数:“./todo”和“o”。 ./todo add
部分将 add
的值分配给 ./todo
参数。
“我是 soham Das Biswas”不会分配给“o”,因为您在通话中没有提到“o”。如果你想为“o”分配一些东西,你需要像 o value_i_want_to_assign
.
这样的东西
您希望您的代码做什么?
有
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
。它们由位置标识,而不是任何类型的 'flag' 字符串。第一个字符串分配给 args
的“./todo”属性,第二个字符串分配给“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
您尝试根据 args.o
值
添加“x”参数
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
表示必需的内容。有多种方法可以改变它,但这会使您和您的用户更难理解输入内容。
我正在处理一个命令行项目,在处理 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
参数。
“我是 soham Das Biswas”不会分配给“o”,因为您在通话中没有提到“o”。如果你想为“o”分配一些东西,你需要像 o value_i_want_to_assign
.
您希望您的代码做什么?
有
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
。它们由位置标识,而不是任何类型的 'flag' 字符串。第一个字符串分配给 args
的“./todo”属性,第二个字符串分配给“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
您尝试根据 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
表示必需的内容。有多种方法可以改变它,但这会使您和您的用户更难理解输入内容。