Python中arg参数笔记之一
初始代码
import os import logging from argparse import ArgumentParser import shutil # This Python script is based on the shell converter script provided in the MipNerF 360 repository. parser = ArgumentParser("Colmap converter") parser.add_argument("--no_gpu", action='store_true') parser.add_argument("--skip_matching", action='store_true') parser.add_argument("--source_path","-s", default="/mnt/data/zdfile/MVGS/Ignatius/images_raw", required=True,type=str) parser.add_argument("--camera", default="OPENCV",type=str) parser.add_argument("--colmap_executable", default="",type=str) parser.add_argument("--resize", action="store_true") parser.add_argument("--magick_executable", default="",type=str) args = parser.parse_args() colmap_command ='"{}"'.format(args.colmap_executable)iflen(args.colmap_executable)>0else"colmap" magick_command ='"{}"'.format(args.magick_executable)iflen(args.magick_executable)>0else"magick" use_gpu =1ifnot args.no_gpu else1.工具库的导入
import os # 操作系统接口,用于文件路径操作from argparse import ArgumentParser # 命令行参数解析核心模块2.参数解析器设置
parser = ArgumentParser("Colmap converter")创建了一个ArgumentParser对象,描述为"Colmap converter",当用户使用-h或–help时会显示此描述。
2.1参数详解
下表列出了所有可用的命令行参数及其作用:
| 参数 | 类型 | 默认值 | 作用 |
|---|---|---|---|
| –no_gpu | 标志 | False | 禁用GPU加速(添加时启用CPU模式) |
| –source_path, -s | 路径 | 必须 | 指定源图像所在的目录路径 |
| –camera | 字符串 | opencv | 设置相机模型 |
关键特性说明:
- 标志参数:action='store_true’意味着当参数出现时值为True,否则为False
- 路径参数:required=True表示–source_path是必须提供的参数
- 相机模型:COLMAP支持多种相机模型,OPENCV是常用的包含畸变参数的模型
2.2默认参数解读
action=‘store_true’
简单来说,store_true用于创建一个命令行开关:指定这个参数,其值就为 True;不指定,则为其默认值 False。它让你的脚本可以方便地通过命令行来开启或关闭某些功能。
当不使用–no_gpu参数时:args.no_gpu=False→ use_gpu=1(启用GPU)
当使用–no_gpu参数时:args.no_gpu=True→ use_gpu=0(禁用GPU)
下面这个表格能帮你快速抓住 store_true及其他相关 action的核心区别:
| action类型 | 作用 | 示例 |
|---|---|---|
| “store_true” | 指定参数则设为 True,不指定则默认为 False。 | –verbose→ args.verbose = True |
| “store_false” | 指定参数则设为 False,不指定则默认为 True。 | –no-clean→ args.clean = False |
| “store” | 默认行为。存储参数后面跟的具体值。 | –name John→ args.name = “John” |
| “store_const” | 存储一个预设的常量值,通常与 const参数配合使用。 | –mode fast(并设置 const=“fast”) → args.mode = “fast” |
核心理解与使用场景
store_true的本质是创建一个标志(flag)。你只需要在命令行中写上这个参数(例如 --verbose),它的值就会自动设置为 True;如果不写,它就是 False。你不需要也不能在参数后面再跟一个值(比如 --verbose True是错误的)
这种特性使其非常适合用来控制一些可选的、非此即彼的功能开关,例如:
- 启用详细输出 (–verbose)
- 启用调试模式 (–debug)
- 执行某些额外操作(如你的脚本中的 --resize和 --skip_matching)
** 示例**
import argparse parser = argparse.ArgumentParser()# 添加一个使用 store_true 的参数 parser.add_argument("--verbose", action="store_true",help="启用详细输出模式") args = parser.parse_args()if args.verbose:print("详细模式已开启!")else:print("正在以普通模式运行。") 2.3 使用技巧
1.关于默认值:action='store_true’已经隐含了 default=False的行为,所以你通常不需要再显式设置 default=False。如果你为其设置 default=True,那么无论命令行是否指定该参数,其值都将为 True,这通常不符合预期,应避免这样使用
2互斥参数组:如果你想确保一组参数(例如 --verbose和 --quiet)不能同时出现,可以将它们放入一个互斥参数组中
3.通过配置文件输入
在Python中,有多种方式可以通过配置文件输入参数,下面我为你详细介绍几种主流方法,并提供一个适合你COLMAP转换脚本的完整解决方案。
配置文件方法对比
| 方法 | 优点 | 优点 | 适用场景 |
|---|---|---|---|
| JSON配置 | 标准格式,无需额外依赖 | 不支持注释,冗长 | 简单配置,Web应用 |
| YAML配置 | 可读性好,支持注释 | 需要安装PyYAML | 复杂配置,机器学习项目 |
| INI配置 | Python内置支持,简单 | 功能相对有限 | 基础项目配置 |
| Python文件 | 最灵活,可编程 | 有安全风险 | 动态配置,复杂逻辑 |
3.1 JSON配置文件(推荐用于简单配置)(这个有点乱,建议参考下一篇文章)
创建 config.json:
{"source_path":"/mnt/data/zdfile/MVGS/Ignatius/images_raw","camera":"OPENCV","colmap_executable":"","resize":false,"magick_executable":"","no_gpu":false,"skip_matching":false}修改你的Python脚本:
import json import argparse defload_config(config_path):"""加载JSON配置文件"""withopen(config_path,'r')as f:return json.load(f)defmain(): parser = argparse.ArgumentParser("Colmap converter")# 创建ArgumentParser对象,设置程序描述。 parser.add_argument("--config",type=str,help="配置文件路径", default="config.json")# 添加--config参数,用于指定配置文件路径,默认值为"config.json"# 定义所有命令行参数 原有的参数定义保持不变 parser.add_argument("--no_gpu", action='store_true') parser.add_argument("--skip_matching", action='store_true') parser.add_argument("--source_path","-s",type=str) parser.add_argument("--camera",type=str, default="OPENCV") parser.add_argument("--colmap_executable",type=str, default="") parser.add_argument("--resize", action="store_true") parser.add_argument("--magick_executable",type=str, default="")# 解析命令行参数(先解析config参数) 第一次解析与配置文件加载 args, remaining_args = parser.parse_known_args()# 这是第一次更新args。此方法先解析已知参数(这里是--config),将其赋值给args,同时将未知参数存入remaining_args(此处未使用)。此步更新了args.config。# 加载配置文件 config = load_config(args.config)# 加载指定路径的JSON配置文件。# 创建最终配置:命令行参数覆盖配置文件 final_config = config.copy()# 创建配置字典的副本,作为最终配置的基础。# 更新为命令行提供的值 cmd_args = parser.parse_args()# 这是第二次也是最后一次更新args(此处变量名为cmd_args)。此方法会解析命令行中的所有参数,更新所有参数的属性。for key, value invars(cmd_args).items():if value isnotNoneand value != parser.get_default(key): final_config[key]= value # 循环遍历解析后的参数,检查参数值是否有效且非默认值。如果是,则用命令行参数值覆盖final_config中的对应值。这实现了命令行参数优先于配置文件的规则。return final_config if __name__ =="__main__": config = main()print("最终配置:", config)这种设计的巧妙之处在于两次对parse_args的调用:
- 第一次解析(parse_known_args):目的是尽早获取–config参数的值,从而确定配置文件的位置。此时其他参数可能还未被正确解析或包含未知值。
- 第二次解析(parse_args):在配置文件加载后,获取所有参数的最终值。此时,任何通过命令行明确提供的参数都会覆盖配置文件中的默认值。
场景1:使用默认配置文件和默认参数值。
python script.py 最终配置将完全来自config.json。
场景2:使用自定义配置文件,并覆盖个别参数。
python script.py --config my_config.json --source_path /new/path --no_gpu 最终配置主要来自my_config.json,但source_path和no_gpu会被命令行参数覆盖。
4.相关模块的基础知识介绍
4.1 argparse模块
python标准库模块argparse用于解析命令行参数,编写用户友好的命令行界面,该模块还会自动生成帮助信息,并在所给参数无效时报错。
#arg_parse.py#coding:utf-8import argparse parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('integers', metavar='N',type=int, nargs='+',help='an integer for the accumulator') parser.add_argument('--sum', dest='accumulate', action='store_const',const=sum, default=max,help='sum the integers (default: find the max)') args = parser.parse_args()print(args.accumulate(args.integers))将上述代码保存为arg_parse.py,在命令行运行该脚本。使用-h选项可以查看帮助信息
$ python prog.py -h usage: prog.py [-h][--sum] N [N ...] Process some integers. positional arguments: N an integer for the accumulator optional arguments: -h, --help show this help message and exit --sum sum the integers (default: find the max)如果不指定–sum选项,则找出输入参数中的最大值,否则求和。
$ python prog.py 12344 $ python prog.py 1234 --sum 10如果给出无效的参数,会给出一个错误信息:
$ python prog.py a b c usage: prog.py [-h][--sum] N [N ...] prog.py: error: argument N: invalid int value: 'a'4.2 ArgumentParser对象
使用argparse的第一步是创建一个 ArgumentParser对象,这个ArgumentParser对象中会保存所有将命令行参数转为python数据类型的必需信息。使用 argparse.ArgumentParser创建ArgumentParser对象。
argparse.ArgumentParser(prog=None, usage=None, epilog=None, parents=[], formatter_class=argparse.HelpFormatter, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True)- 1.prog
默认情况下, ArgumentParser对象根据sys.argv[0]的值(不包括路径名)生成帮助信息中的程序名。 - 2.usage
默认情况下,ArgumentParser对象可以根据参数自动生成用法信息 - 3.description
description 用于展示程序的简要介绍信息,通常包括:这个程序可以做什么、怎么做。在帮助信息中 description位于用法信息与参数说明之间 - 4.epilog
与description类似,程序的额外描述信息,位于参数说明之后
4.3 add_argument()方法
参考 https://blog.ZEEKLOG.net/guoyajie1990/article/details/76739977
rgumentParser.add_argument(name or flags...[,action][,nargs][,const][,default][,type][,choices][,required][,help][,metavar][,dest])1.name 或 flags
指定一个可选参数或位置参数
>>> parser.add_argument('-f','--foo')#指定一个可选参数>>> parser.add_argument('bar')#指定一个位置参数可选参数是以’-‘为前缀的参数,剩下的就是位置参数
>>> parser = argparse.ArgumentParser(prog='PROG')>>> parser.add_argument('-f','--foo')>>> parser.add_argument('bar')>>> parser.parse_args(['BAR']) Namespace(bar='BAR', foo=None)>>> parser.parse_args(['BAR','--foo','FOO']) Namespace(bar='BAR', foo='FOO')>>> parser.parse_args(['--foo','FOO']) usage: PROG [-h][-f FOO] bar PROG: error: too few arguments 2.action
action参数指定应该如何处理命令行参数,预置的操作有以下几种:
action=’store’ 仅仅保存参数值,为action默认值
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo')>>> parser.parse_args('--foo 1'.split()) Namespace(foo='1')action=’store_const’ 与store基本一致,但store_const只保存const关键字指定的值``
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', action='store_const', const=42)>>> parser.parse_args('--foo'.split()) Namespace(foo=42)>>> parser.parse_args('--foo 34'.split()) usage: arg_parse.py [-h][--foo] arg_parse.py: error: unrecognized arguments:34action=’store_true’或’store_false’ 与store_const一致,只保存True和False
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', action='store_true')>>> parser.add_argument('--bar', action='store_false')>>> parser.parse_args('--foo --bar'.split()) Namespace(bar=False, foo=True)action=’append’ 将相同参数的不同值保存在一个list中
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', action='append')>>> parser.parse_args('--foo 1 --foo 2'.split()) Namespace(foo=['1','2'])action=’count’ 统计该参数出现的次数
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--verbose','-v', action='count')>>> parser.parse_args('-vvv'.split()) Namespace(verbose=3)除了上述几种预置action,还可以自定义action,需要继承Action并覆盖call和init方法。
>>>classFooAction(argparse.Action):...def__init__(self, option_strings, dest, nargs=None,**kwargs):...if nargs isnotNone:...raise ValueError("nargs not allowed")...super(FooAction, self).__init__(option_strings, dest,**kwargs)...def__call__(self, parser, namespace, values, option_string=None):...print('%r %r %r'%(namespace, values, option_string))...setattr(namespace, self.dest, values)...>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', action=FooAction)>>> parser.add_argument('bar', action=FooAction)>>> args = parser.parse_args('1 --foo 2'.split()) Namespace(bar=None, foo=None)'1'None Namespace(bar='1', foo=None)'2''--foo'>>> args Namespace(bar='1', foo='2')3.nargs
默认情况下 ArgumentParser对象将参数与一个与action一一关联,通过指定 nargs可以将多个参数与一个action相关联。nargs支持值如下:
N (整数) N个命令行参数被保存在一个list中
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', nargs=2)>>> parser.add_argument('bar', nargs=1)>>> parser.parse_args('c --foo a b'.split()) Namespace(bar=['c'], foo=['a','b'])?’ 如果存在该参数且给出了参数值,则从命令行取得该参数,如果存在该参数但未给出参数值,则从const关键字中取得参数值,如果不存在该参数,则将生成默认值。可能表述地不到位,还是看结合代码理解吧
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', nargs='?', const='c', default='d')>>> parser.add_argument('bar', nargs='?', default='d')>>> parser.parse_args('XX --foo YY'.split()) Namespace(bar='XX', foo='YY')>>> parser.parse_args('XX --foo'.split()) Namespace(bar='XX', foo='c')>>> parser.parse_args(''.split()) Namespace(bar='d', foo='d')‘*’命令行参数被保存在一个list中
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', nargs='*')>>> parser.add_argument('--bar', nargs='*')>>> parser.add_argument('baz', nargs='*')>>> parser.parse_args('a b --foo x y --bar 1 2'.split()) Namespace(bar=['1','2'], baz=['a','b'], foo=['x','y'])4.default
如果参数可以缺省,default指定命令行参数不存在时的参数值。
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', default=42)>>> parser.parse_args('--foo 2'.split()) Namespace(foo='2')>>> parser.parse_args(''.split()) Namespace(foo=42)5.type
默认情况下,ArgumentParser对象将命令行参数保存为字符串。但通常命令行参数应该被解释为另一种类型,如 float或int。通过指定type,可以对命令行参数执行类型检查和类型转换。通用的内置类型和函数可以直接用作type参数的值:
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('foo',type=int)>>> parser.add_argument('bar',type=open)>>> parser.parse_args('2 temp.txt'.split()) Namespace(bar=<_io.TextIOWrapper name='temp.txt' encoding='UTF-8'>, foo=2)- choices
将命令行参数的值限定在一个范围内,超出范围则报错
>>> parser = argparse.ArgumentParser(prog='game.py')>>> parser.add_argument('move', choices=['rock','paper','scissors'])>>> parser.parse_args(['rock']) Namespace(move='rock')>>> parser.parse_args(['fire']) usage: game.py [-h]{rock,paper,scissors} game.py: error: argument move: invalid choice:'fire'(choose from'rock','paper','scissors')>>> parser = argparse.ArgumentParser(prog='doors.py')>>> parser.add_argument('door',type=int, choices=range(1,4))>>>print(parser.parse_args(['3'])) Namespace(door=3)>>> parser.parse_args(['4']) usage: doors.py [-h]{1,2,3} doors.py: error: argument door: invalid choice:4(choose from1,2,3)7.required
指定命令行参数是否必需,默认通过-f –foo指定的参数为可选参数
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', required=True)>>> parser.parse_args(['--foo','BAR']) Namespace(foo='BAR')>>> parser.parse_args([]) usage: argparse.py [-h][--foo FOO] argparse.py: error: option --foo is required 8.dest
dest 允许自定义ArgumentParser的参数属性名称
>>> parser = argparse.ArgumentParser()>>> parser.add_argument('--foo', dest='bar')>>> parser.parse_args('--foo XXX'.split()) Namespace(bar='XXX')5.parse_args()详解
参考:https://blog.ZEEKLOG.net/zjc910997316/article/details/85319894
5.1 初始化
# 1引入模块import argparse # 2建立解析对象 parser = argparse.ArgumentParser()# 3增加属性:给xx实例增加一个aa属性 # xx.add_argument("aa") parser.add_argument("echo")# 4属性给与args实例: 把parser中设置的所有"add_argument"给返回到args子类实例当中, 那么parser中增加的属性内容都会在args实例中,使用即可。 args = parser.parse_args() parser.parse_args()# 打印定位参数echoprint(args.echo)运行的话,在 python argp.py 后面加上 abcd (任意);
其将输出 “abcd”。
因为我们把 abcd 赋给了 args.echo了。
给其设置help:
parser.add_argument(“echo”, help = “echo is here~”)
在命令行中输入:
python argp.py -h
就可以得到相关的帮助信息。
5.2 type
假设我们写一个文件,在命令行将其编译时,同时输入一个数字,返回一个平方:
因为 parse.add_argument() 对于接受的值默认其为str,如果要将之视为int类型,额外加一句 “type=int”。
# 1引入模块import argparse # 2建立解析对象 parser = argparse.ArgumentParser()# 3增加属性:在命令行中,该py文件希望用户能给他一个参数,最终将之转化为:args.square parser.add_argument("square",help="To sqaure the number given",type=int)# 4属性给与args实例:add_argument 返回到 args 子类实例 args = parser.parse_arg()print(args.square**2)有了type程序也可以自动过滤掉相关的不符合类型的参数输入。
5.3 可选参数
在 add_argument 前,给属性名之前加上“- -”,就能将之变为可选参数。
# 1引入模块import argparse # 2建立解析对象 parser = argparse.ArgumentParser()# 3增加属性:这里的bool是一个可选参数,返回给args的是 args.bool parser.add_argument("--bool",help="Whether to pirnt sth.")# 4属性给与args实例: parser中增加的属性内容都在args实例中 args = parser.parse_args()# 如果有输入内容,则打印1if args.bool:print('bool = 1')—输入:
python argp.py --bool 1
—得到:
bool = 1
可选参数"–bool":
既然是可选的,如果不指定(就是不使用它)的话,对应的变量会被设置为None。
对于简单程序,我们可能只需要两种值 True or False:
action = “store_true” 默认操作True :
我们可以在原有的程序的基础上,在 add_argument 中多加一个参数:
action = “store_true”
这个时候,只要在命令行中加个–bool,args.bool就是 True 了,无需再加上之后的赋值内容,加了反而会报错。
—输入:
python argp.py --bool
—得到:
bool = 1
required=True :
但是,如果在 parser.add_argument(…, action = “store_true”,required=True) 的话,那么这个参数就是必须的,因为他是required。
ps: 这里指的参数是 --bool 必须写不然会报错
—输入:
python argp.py --bool
—得到:
bool = 1
5.4 参数简写
parser.add_argument(“-b”,“–bool”,action=“store_true”)
这样,在程序内部我们依旧使用 args.bool,但是在命令行当中我们只需要多写一个“-b”就好了。
—输入:
python argp.py -b
—得到:
bool = 1
5.5 混合定位参数和可选参数
当我们使用多个 parser.add_argument(…) 的时候,若将之视为可选参数,无则为None。
# 1引入模块import argparse # 2建立解析对象 parser = argparse.ArgumentParser()# 3增加属性 parser.add_argument("-b","--bool",help="to show the ans in a sentencen form",action ="store_true") parser.add_argument("square",type=int)# 4属性赋予实例args args = parser.parse_args() ans = args.square**2# 得到的效果为:一旦输入“-b”然后再输入相关的参数,就可以得到我们需要的结果了,不输入“-b”我们还是可以得到结果,只不过是另外一种方式而已。if args.bool:print("the square of {} = {}".format(args.square,ans))else:print(ans)—输入:
python test.py -b 2 (或者 python test.py 2)
—得到:
4
5.6 限制输入的值
如 parser.add_argument(“-b”, “–bool”, choices = [0,1,2], help=“you can only input 0 1or 2.”, type = int)
其中,choice 可以限定我们能够输入的数为0,1,2其中一个。
这里的 type = int 必不可少,不然会报错。
import argparse parser = argparse.ArgumentParser() parser.add_argument("-b","--bool", choices =[0,1,2],type=int) args = parser.parse_args() ans = args.bool**2print(ans)—输入:
python test.py -b 2
—得到:
4
5.7 参数值和顺序
- 一般我们要把可选参数最后add(带- or – 的为可选参数)
- 不可选参数放前面add
- 而在命令行里面输入代码时,程序会先赋值“先add的参数选项”。
比如我先 parser.add_argument(“a”,…) 再b;
输入命令行的时候: python xx.py x y,这个时候, args.a=x ; args.b=y。
\
5.8 高级用法
一个py文件的文件名字为"file"
我们可以通过 group 方法,来让 group 组的参数不可以被同时指定:
# 1导入模块import argparse # 2建立解析对象 parser = argparse.ArgumentParser()# 3添加属性 group = parser.add_mutually_exclusive_group() group.add_argument("-f","--form", action="store_true") group.add_argument("-F","--Form", action="store_true") parser.add_argument("x",type=float)// python __file__.py -x 10, 这个前面“x”不需要写成"-x"?? parser.add_argument("y",type=float)# 4属性赋予实例args args = parser.parse_args() ans = args.x**args.y if args.form:print("{} to the power {} equals {}".format(args.x, args.y, ans))elif args.Form:print("{}^{} = {}".format(args.x,args.y,ans))else:print(ans)