argparse 是 Python 内置的用于解析命令行参数的库,它可以帮助开发者创建用户友好的命令行界面,从而方便用户通过命令行向程序传递参数。通过 argparse,你可以定义程序可以接受的命令行参数的类型、数量以及帮助文本等。
本文主要包括以下内容:
一、 argparse 的基本用法:
#导入argparse模块:
import argparse
#创建ArgumentParser对象:
parser = argparse.ArgumentParser(description='Description of your program')
#添加命令行参数:
parser.add_argument('arg_name', type=str, help='Help text for this argument')
#解析命令行参数:
args = parser.parse_args()
#使用解析得到的参数:
print(args.arg_name)
arg_name: 参数名称,可以通过 args.arg_name 来访问参数的值。
type: 参数的类型,可以是 int、float、str 等。
help: 参数的帮助文本,会在用户请求帮助时显示。
parser.add_argument 是 argparse.ArgumentParser 类的一个方法,用于向解析器添加命令行参数选项。
parser.add_argument(name or flags, action, nargs, const, default, type, choices, required, help, metavar)
name or flags:参数的名称或选项。可以是位置参数的名称(无前缀)或带有前缀 - 或 - - 的选项名称。例如,“filename” 是一个位置参数的名称,而 “- -output” 是一个选项名称。
action:参数的动作。它指定当命令行中出现该参数时,应该采取什么操作。常用的动作有 “store”(保存值,默认)、“store_const”(保存常量值)、“store_true”(保存 True)、“store_false”(保存 False)、“append”(追加值到列表中)、“append_const”(追加常量到列表中)等。
nargs:参数的数量。它指定该参数接受的值的数量。常用的取值有 None(默认,接受一个值)、‘?’(接受零个或一个值)、‘*’(接受零个或多个值)、‘+’(接受至少一个值)等。
const:常量值。当参数使用 store_const 动作时,该参数指定存储的常量值。
default:默认值。当命令行中没有提供该参数时,使用的默认值。
type:值的类型。指定参数值应该被解析成的数据类型。
choices:值的限制。指定允许的参数值,只有提供的值才会被接受。
required:是否必需。如果设置为 True,则该参数为必需参数,不提供将报错。
help:帮助文本。用于显示该参数的帮助信息,通常是参数的简要描述。
metavar:用于显示帮助信息中参数的名称。
以上参数中,name or flags 、type和 help 是最常用的参数,其他参数根据需要使用。在实际使用时,您可以根据您的命令行参数需求,灵活地选择适合的参数设置。
接下来,让我们通过一个简单的例子来说明 argparse 的用法。假设我们要编写一个简单的计算器程序,能够对两个数进行加、减、乘、除操作。
新建一个名为calculator的pythonfile,输入以下代码:
import argparse
def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x, y):
return x / y
parser = argparse.ArgumentParser(description='Simple calculator')
parser.add_argument('operation', type=str, help='Operation to perform: add, subtract, multiply, divide')
parser.add_argument('num1', type=float, help='First number')
parser.add_argument('num2', type=float, help='Second number')
args = parser.parse_args()
if args.operation == 'add':
result = add(args.num1, args.num2)
elif args.operation == 'subtract':
result = subtract(args.num1, args.num2)
elif args.operation == 'multiply':
result = multiply(args.num1, args.num2)
elif args.operation == 'divide':
result = divide(args.num1, args.num2)
else:
print('Invalid operation')
exit(1)
print('Result:', result)
通过运行该程序,并传递参数,可以执行不同的操作。例如在terminal中运行以下的命令:
python calculator.py add 10 5
输出结果:
Result: 15.0
或:
python calculator.py divide 10 5
输出结果:
Result: 2.0
使用 python calculator.py -h 可以查看帮助文档
python calculator.py -h
显示:
usage: calculator.py [-h] operation num1 num2
Simple calculator
positional arguments:
operation Operation to perform: add, subtract, multiply, divide
num1 First number
num2 Second number
optional arguments:
-h, --help show this help message and exit
如此,用户可以通过命令行传递参数并执行不同的计算操作。
二、parser.add_argument()函数
有时我们会遇到同时有长短名字的parser.add_argument()代码,如下面所示:
# 添加一个可选参数"-s"或"--steps",用于指定MCTS步数,默认值为1000,同时提供帮助信息
parser.add_argument("-s", "--steps", type=int, default=1000, help="Number of MCTS steps"
parser.add_argument(): 这是argparse模块中的一个方法,用于添加一个命令行参数。通过调用这个方法,我们可以定义我们希望程序接受的命令行参数的规则和属性。
“-s” 和 “–steps”: 这两个参数是命令行参数的名字。“-s” 是一个简短的标志,而 “–steps” 是一个长标志。可以通过这两个标志来指定参数的值。
type=int: 这是参数的类型说明。在这里,参数值将会被解释为整数类型。
default=1000: 这是参数的默认值。如果在命令行没有提供 -s 或 --steps 参数,则程序会使用默认值 1000。
help="Number of MCTS steps": 这是对参数的简短描述,它会在用户使用 --help 标志来查看帮助时显示出来。在这里,参数是用来指定MCTS(蒙特卡洛树搜索)步骤的数量。
总结起来,这段代码告诉我们的程序可以通过以下方式来使用 -s 或 --steps 参数:
-s 2000 或 --steps 2000:在命令行中指定参数名和值。
如果没有在命令行中指定该参数,则默认使用 1000 作为参数值。
当用户需要查看帮助时,会显示出参数的描述:“Number of MCTS steps”。
在argparse模块中,可以同时为一个命令行参数定义一个简短的标志(通常是单个字符,例如"-s")和一个长标志(通常是单词,例如"–steps")。这种做法是为了方便用户在命令行中使用不同的方式来指定同一个参数,使得命令行更加灵活和易用。
#使用"-s"标志的示例:
python my_script.py -s 2000
#使用"--steps"标志的示例:
python my_script.py --steps 2000
这两种方式都会将参数设置为2000。简短的标志通常用于方便的命令行输入,而长标志通常用于更明确和易读的选项名称。
同时定义两个标志没有本质的区别,它们只是在命名和使用上的不同表现。程序会根据用户提供的标志来识别参数,并将其值设置为用户指定的值或默认值。
三、关于 - 与 - -
在使用 argparse 解析命令行参数时,参数名通常以 “- -” 开头。这样做的目的是区分命令行参数和位置参数。
在原始的代码中,没有在参数名前加 “- -” 是因为这段代码使用了位置参数(Positional Arguments)。位置参数是不需要前缀 “- -” 的,它们是根据参数在命令行中出现的位置来解析的。新建一个名为script.py的Python file。
#script.py
def parse_args():
parser = argparse.ArgumentParser("TreEnhance Hyperparams")
a = parser.add_argument
a("base_dir", help="BASE DIRECTORY")
a("expname",help="Name of the run")
a("dropout", type=float, default=0.6, help="Dropout")
a("num_images", type=int, default=100, help="number of Images")
a("num_steps", type=int, default=10, help="number of steps")
a("val_images", type=int, default=100, help="number of val images")
a("lr", type=float, default=0.001, help="learning rate")
a("size", type=int, default=256, help="image size")
a("num_gen", type=float, default=256, help="number of generation")
a("bs", type=int, default=16, help="batch size")
a("lambd", type=int, default=20, help="lambda in the loss function")
a("loops", type=int, default=5, help="number of optimization loops")
return parser.parse_args()
例如,当你运行这个脚本时,需要按照函数参数的顺序提供相应的值,你可以这样运行它:
python my_script.py ./path/to/base_dir my_expname 0.6 100 10 100 0.001 256 256 16 20 5
在上面的命令行中,按照函数 parse_args() 的参数顺序提供了相应的值。这些值将按照参数的顺序依次赋给对应的参数,赋值结果如下:
base_dir:./path/to/base_dir
expname: my_expname
dropout: 0.6
num_images:100
以此类推
不过,为了提高可读性并更加灵活地指定参数,通常建议使用长格式的命令行参数,即在参数名前加 “–”,如下面的代码所示:
#script.py
def parse_args():
parser = argparse.ArgumentParser("TreEnhance Hyperparams")
a = parser.add_argument
a("--basedir", nargs='?', default='./', help="BASE DIRECTORY")
a("--expname", default="default_exp", help="Name of the run")
a("--dropout", type=float, default=0.6, help="Dropout")
a("--num_images", type=int, default=100, help="number of Images")
a("--num_steps", type=int, default=100, help="number of steps") # 每个epoch训练的迭代步数
a("--val_images", type=int, default=100, help="number of val images")
a("--lr", type=float, default=0.001, help="learning rate")
a("--size", type=int, default=256, help="image size")
a("--num_gen", type=float, default=50, help="number of generation") # 相当于训练的epoch数,256
a("--bs", type=int, default=8, help="batch size")
a("--lambd", type=int, default=20, help="lambda in the loss function")
a("--loops", type=int, default=5, help="number of optimization loops")
return parser.parse_args()
使用长格式的命令行参数可以在命令行中指定参数值,而不需要按照特定顺序。这样会更易读,并且允许在命令行中选择性地提供参数,你可以这样运行:
python my_script.py --basedir /path/to/base_dir --expname my_expname --dropout 0.6 --num_images 100 --num_steps 10 --val_images 100 --lr 0.001 --size 256 --num_gen 256 --bs 16 --lambd 20 --loops 5
总结起来,为命令行参数同时提供简短标志和长标志是为了增加命令行的灵活性和可读性,使得用户可以根据自己的喜好和需求来选择合适的方式来指定参数值。
四、args = parser.parse_args()与return parser.parse_args()的区别
args = parser.parse_args() 和 return parser.parse_args() 的区别在于它们的返回值和用途。
args = parser.parse_args(): 这行代码将调用 parser.parse_args() 方法来解析命令行参数,并将解析后的结果存储在变量 args 中。args 是一个命名空间(Namespace)对象,其中包含了解析后的命令行参数。你可以通过属性的方式访问这些参数的值,例如 args.expname、args.num_images 等。
# 示例
args = parser.parse_args()
print(args.expname) # 输出:命令行参数中的 expname 参数值
print(args.num_images) # 输出:命令行参数中的 num_images 参数值
return parser.parse_args(): 这行代码将在函数中返回 parser.parse_args() 方法的结果。也就是说,当你调用这个函数时,它将解析命令行参数,并将解析后的结果作为函数的返回值。这样,你可以在调用函数时直接获取解析后的参数值,而无需再单独赋值给一个变量。
# 示例
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("--expname", help="Name of the run")
parser.add_argument("--num_images", type=int, default=100, help="number of Images")
# 添加其他命令行参数...
return parser.parse_args()
# 在其他地方调用函数
args = parse_args()
print(args.expname) # 输出:命令行参数中的 expname 参数值
print(args.num_images) # 输出:命令行参数中的 num_images 参数值
总结:parser.parse_args() 方法用于解析命令行参数,并将解析后的结果存储在命名空间对象中。args = parser.parse_args() 将这个命名空间对象赋值给变量 args,使得你可以通过属性的方式访问命令行参数的值。return parser.parse_args() 将解析后的结果作为函数的返回值,使得你可以在调用函数时直接获取解析后的参数值,而无需额外的赋值。