在 Python 脚本中采用命令行参数的最佳方式

Posted

技术标签:

【中文标题】在 Python 脚本中采用命令行参数的最佳方式【英文标题】:Best way to take Command Line Arguments in Python Script 【发布时间】:2022-01-06 20:00:47 【问题描述】:

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

为了阐明用例,这里有一个例子。假设我有 3 个强制参数:mode, foo, bar 和 5 个可选参数:op1, op2, op3, op4, op5。可以说,mode 可以有 3 个值:m1, m2, m3。如果modem1,则op1 and op2 是强制性的。如果modem2op3 是强制性的,如果modem3op4 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。如果也有可能做这样的事情,那对我来说将是额外的好处。

谢谢。

【问题讨论】:

【参考方案1】:

您的程序似乎正在处理多个不同的任务。支持这一点的方法是将解析器拆分为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

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

【讨论】:

这里,m1 似乎是常见的 args 参数,而不是 argparse 给出的键控参数。是否有可能有类似:python3 args.py --mode m1 被子解析器读取? 我添加了一种方法来检查所选的特定模式。这是否回答你的问题?您也可以将required=True 添加到add_subparsers() 以确保模式存在。 但是我如何为这个脚本添加foobar,我的强制参数(我需要与mode一起提供)? 它们可以添加到主解析器中,就像您之前所做的那样。我扩展了我的答案。 @vish4071 完成!

以上是关于在 Python 脚本中采用命令行参数的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

命令行运行Python脚本时传入参数的三种方式

将文件x中指定的函数作为命令行参数传递给python中的文件y的最佳方法

Python语言命令行参数解析接收参数执行脚本的三种方法

命令行运行Python脚本时传入参数的三种方式

如何根据命令行输入包含py文件?

python开发命令行脚本