在 Python 脚本中获取命令行参数的最佳方式

Best way to take Command Line Arguments in Python Script

在我的 Python 脚本中,我有很多命令行参数。其中一些是强制性的,而另一些是可选的。对于强制参数的某些值,一些可选的也是强制的。在这种命令行参数的情况下,最好的方法是什么。我正在使用 argparse.Argumentparser 用于我的目的。

为了阐明用例,这里有一个例子。假设我有 3 个强制参数:mode, foo, bar 和 5 个可选参数:op1, op2, op3, op4, op5。比方说,mode 可以有 3 个值:m1, m2, m3。如果 modem1,则 op1 and op2 是必需的。如果 modem2,则 op3 是强制性的,如果 modem3,则 op4 and op5 是强制性的。

将其写入代码的最佳方式是什么?我现在所做的似乎过于详尽,只是觉得必须有更好的方法来做到这一点。

-> 当前代码

import argparse

# create and execute parser
my_parser = argparse.ArgumentParser(description="Demo")
my_parser.add_argument("--mode", action="store", type=str, required=True)
my_parser.add_argument("--foo", action="store", type=str, required=True)
my_parser.add_argument("--bar", action="store", type=str, required=True)
my_parser.add_argument("--op1", action="store", type=str, required=False, default=None)
my_parser.add_argument("--op2", action="store", type=str, required=False, default=None)
my_parser.add_argument("--op3", action="store", type=str, required=False, default=None)
my_parser.add_argument("--op4", action="store", type=str, required=False, default=None)
my_parser.add_argument("--op5", action="store", type=str, required=False, default=None)
args = my_parser.parse_args()
try:
    if args.mode == "m1":
        op1 = args.op1.lower()
        op2 = args.op2.lower()
    if args.mode == "m2":
        op3 = args.op3.split(',')
    if args.mode == "m3":
        op4 = args.op4.lower()
        op5 = args.op5.lower()
except AttributeError:
    print("Wrong mode set for optional arguments")
    exit()

如您所见,即使这个示例在美学上“看起来”很糟糕(尤其是 try 块解析),而且在我的案例中我有很多可选参数要处理。任何帮助将不胜感激。

此外,这种方法并不完全强制用户输入,例如,op1 and op2 以防他的 mode=m1。如果也可以做这样的事情,那对我来说就是额外的好处。

谢谢。

您的程序似乎正在处理多个不同的任务。支持这一点的方法是将您的解析器拆分为 sub-commands:

import argparse

parser = argparse.ArgumentParser(description="Demo")
parser.add_argument("--foo", required=True)
parser.add_argument("--bar", required=True)
subparsers = parser.add_subparsers(dest='mode', required=True)

m1_parser = subparsers.add_parser('m1', help='mode 1')
m1_parser.add_argument("--op1", required=True)
m1_parser.add_argument("--op2", required=True)
m1_parser.add_argument("--op3")
m1_parser.add_argument("--op4")
m1_parser.add_argument("--op5")

m2_parser = subparsers.add_parser('m2', help='mode 2')
m2_parser.add_argument("--op1")
m2_parser.add_argument("--op2")
m2_parser.add_argument("--op3", required=True)
m2_parser.add_argument("--op4")
m2_parser.add_argument("--op5")

m3_parser = subparsers.add_parser('m3', help='mode 3')
m3_parser.add_argument("--op1")
m3_parser.add_argument("--op2")
m3_parser.add_argument("--op3")
m3_parser.add_argument("--op4", required=True)
m3_parser.add_argument("--op5", required=True)

args = parser.parse_args()

if args.mode == 'm1':
    print(args.op1) # it will always exist

用法:

$ python3 args.py m1
usage: args.py m1 [-h] --op1 OP1 --op2 OP2 [--op3 OP3] [--op4 OP4] [--op5 OP5]
args.py m1: error: the following arguments are required: --op1, --op2

虽然这看起来有些重复,但您现在可以选择为特定于子命令的各种选项提供更好的名称。