python - 如何正确使用可选的 argparse 参数和子解析器
问题描述
我正在尝试编写一个小应用程序,它可以根据 argparse 中指定的参数执行多项操作。
我对必须始终指定的文件目录使用位置参数(soundfiledir),但之后我想根据我希望应用程序执行的内容指定参数。例如,-A 标志将运行一组特定的作业(python main.py [声音文件路径] -A)
parser = argparse.ArgumentParser()
parser.add_argument('soundfiledir', type=soundfiledir_format, help = "Specify soundfile directory") #positional argument. must always be provided.
parser.add_argument('-A', '--all', action = "store_true", help = "If this flag is specified, the program will transcribe all the sound files in the sound file directory (with timestamps), and will automatically concatenate files recorded close in time")
if args.all:
does stuff
除此之外,我还使用子解析器。例如,可以使用一些选项(python main.py [soundfile path] fileconcatenator -a 15)指定名为 fileconcatenator (python main.py [soundfile path] fileconcatenator) 的子解析器
subparser = parser.add_subparsers(dest = 'command')
fileconcatenator_parser = subparser.add_parser('fileconcatenator', help = "Concatenates sound files together")
group1 = fileconcatenator_parser.add_mutually_exclusive_group(required=True)
group1.add_argument('-a','--autoconcat',type = positive_int, nargs = "?", const = 3, default = None, \
help="Concatenate audio files recorded close in time. By default any file recorded within 3mns of each other.")
group1.add_argument('-m', '--manconcat', type = list, default = [], \
help = "Concatenate audio files specified as a list.")
fileconverter_parser = subparser.add_parser('fileconverter',help = "Converts files to 16kHz mono wav")
fileconverter_parser.add_argument('-f', '--filestoconvert', type = list, required=True, default = ["All"], \
help = "Specify which files to convert.")
注意:您可能会注意到我将类型设置为 positive_int,这是用户指定的类型,使用
def positive_int(s):
try:
value = int(s)
return int(s)
except ValueError:
raise argparse.ArgumentTypeError(f"Expected positive integer got {s!r}")
if value <= 0:
raise argparse.ArgumentTypeError(f"Expected positive integer got {s!r}")
总的来说,我的设置如下:
def main():
if args.all:
do stuff
if args.autoconcat is None:
pass
else:
do stuff
问题是,当我运行python main.py [soundfile path] -A时,我得到AttributeError: 'Namespace' object has no attribute 'autoconcat'
该程序仍在运行(因为 if args.autoconcat 出现在 if args.all 块之后),但我想知道我做错了什么。
非常感谢任何帮助。如果您觉得不清楚,我会修改问题。
解决方案
请注意, parse_args() 返回的对象将仅包含主解析器和命令行选择的子解析器(而不是任何其他子解析器)的属性。所以上例中,指定a命令时,只存在foo和bar属性,指定b命令时,只存在foo和baz属性。
这正是您的情况:您没有调用程序子命令fileconcatenator
,因此该args
对象将不包含该子命令的参数,例如 autoconcat
。您必须首先检查调用了哪个子命令。这可以通过为所有子命令设置一个通用选项来完成,命令行用户无法修改该选项。它将为每个子命令单独设置,当子命令 a 被调用时,该参数的值为 a,而当子命令 b 被调用时,该参数的值为 b。这可以通过set_defaults
像这样调用每个子解析器来实现:
fileconcatenator_parser = subparser.add_parser('fileconcatenator', help = "Concatenates sound files together")
fileconcatenator_parser.set_defaults(parser_name="fileconcatenator")
# adding some arguments here
fileconverter_parser = subparser.add_parser('fileconverter',help = "Converts files to 16kHz mono wav")
fileconverter_parser.set_defaults(parser_name="fileconverter")
#adding some arguments here
然后在 main 中,首先检查parser_name
是 fileconverter 还是 fileconcatenator,然后根据调用的子命令检查参数。
def main():
args = parser.parse_args()
if args.parser_name == "fileconverter":
# do something with args.filestoconvert
elif args.parser_name == "fileconcatenator":
if args.autoconcat is None:
pass
else:
# do something
您可能必须调用set_defaults(parser_name="main")
主解析器才能使其工作。
推荐阅读
- kotlin - 如何捕获被拒绝的承诺并继续使用 kovenant 进行承诺更改
- laravel - 在 Hostinger 上部署 Laravel 项目
- c# - 如何用共享路径中的单个反斜杠替换双反斜杠
- python - 如何将购买 DataFrame 转换为 Spark DistributedMatrix 类型以计算项目之间的相似性?
- maven - Maven 原型:生成强制 groupId 作为包结构
- c++ - g ++ c ++ 17类模板参数推导在非常特定的情况下不起作用
- python - 如何将图像分析结果添加到 python 中的数据框中(对于混淆矩阵)?
- r - R Shiny 可以用于导入文件、运行 R 脚本和导出文件吗?
- spring-boot - s3 入站通道适配器中的本地目录表达式
- android - Android X86 上的 IMEI “未知”