如何正确使用可选的 argparse 参数和子解析器
How to use optional argparse argument and subparsers properly
我正在尝试编写一个小应用程序,它可以根据 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
除此之外,我还使用了子解析器。例如,可以使用一些选项指定名为 fileconcatenator (python main.py [soundfile path] fileconcatenator) 的子解析器 (python main.py [soundfile path] fileconcatenator -a 15)
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' 对象没有属性 'autoconcat'
程序仍然 运行s(因为 if args.autoconcat 出现在 if args.all 块之后),但我想知道我做错了什么。
非常感谢任何帮助。如果你觉得不清楚我会修改问题。
引自 Python argparse docs:
Note that the object returned by parse_args() will only contain attributes for
the main parser and the subparser that was selected by the command line (and not
any other subparsers). So in the example above, when the a command is specified,
only the foo and bar attributes are present, and when the b command is specified,
only the foo and baz attributes are present.
这正是您的情况:您没有调用程序子命令 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")
让它发挥作用。
我正在尝试编写一个小应用程序,它可以根据 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
除此之外,我还使用了子解析器。例如,可以使用一些选项指定名为 fileconcatenator (python main.py [soundfile path] fileconcatenator) 的子解析器 (python main.py [soundfile path] fileconcatenator -a 15)
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' 对象没有属性 'autoconcat'
程序仍然 运行s(因为 if args.autoconcat 出现在 if args.all 块之后),但我想知道我做错了什么。
非常感谢任何帮助。如果你觉得不清楚我会修改问题。
引自 Python argparse docs:
Note that the object returned by parse_args() will only contain attributes for the main parser and the subparser that was selected by the command line (and not any other subparsers). So in the example above, when the a command is specified, only the foo and bar attributes are present, and when the b command is specified, only the foo and baz attributes are present.
这正是您的情况:您没有调用程序子命令 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")
让它发挥作用。