使用 python optparse 设置默认值时检查是否传递了 arg

checking if arg was passed when default is set with python optparse

当某个参数有默认值时,我想检查该参数是否实际传递到命令行。

特别是在我的例子中,我使用的是 SCons,而 scons 有一个 class 继承自 pythons optparse。所以到目前为止我的代码是这样的:

from SCons.Environment import Environment
from SCons.Script.SConsOptions import Parser

MAIN_ENV = Environment() 
argparser = Parser(MAIN_ENV._get_major_minor_revision(SCons.__version__))
print(argparser.parse_args())

它打印所有带有值的 args,但我无法判断其中一个 args 是否已设置或仅具有默认值。在我查看 SCons 'num_jobs' 选项的情况下,默认为 1。我想检查用户是否提供了 num_jobs 值,如果是,则使用它,否则只需设置 num_jobs到系统上报的CPU数量。

我可以像这样使用 sys.argv,但更喜欢使用选项解析器的更清晰的选项:

###################################################
# Determine number of Jobs
# start by assuming num_jobs was not set
NUM_JOBS_SET = False
if GetOption("num_jobs") == 1:
    # if num_jobs is the default we need to check sys.argv
    # to see if the user happened to set the default
    for arg in sys.argv:
        if arg.startswith("-j") or arg.startswith("--jobs"):
            if arg == "-j" or arg == "--jobs":
                if(int(sys.argv[sys.argv.index(arg)+1]) == 1):
                    NUM_JOBS_SET = True
            else:
                if arg.startswith("-j"):
                    if(int(arg[2:]) == 1):
                        NUM_JOBS_SET = True
else:
    # user must have set something if it wasn't default
    NUM_JOBS_SET = True

# num_jobs wasn't specificed so let use the
# max number since the user doesn't seem to care
if not NUM_JOBS_SET:
    NUM_CPUS = get_num_cpus()
    print("Building with " + str(NUM_CPUS) + " parallel jobs")
    MAIN_ENV.SetOption("num_jobs", NUM_CPUS)
else:
    # user wants a certain number of jobs so do that
    print("Building with " + str(GetOption('num_jobs')) + " parallel jobs")

我尝试使用 pythons OptionParser,但是如果我在 scons 脚本中从 python 的 OptionParser 调用 parse_args(),SCons 解析器似乎不起作用,它无法识别有效选项。

如果有人举例说明如何检查 arg 是否仅通过 pythons optparse 传递,那应该足以让我进入 scons 选项解析器。

我不确定这是否能解决你的问题,但你可以编写装饰器,在装饰器中你可以找到是否传递了参数。

我提供的是基本示例。

def deco(fun):
    def wraper(*args, **kwargs):
        if 'name' in kwargs:
            print('Will use default parameter');
        return fun(*args, **kwargs)

    return wraper

@deco
def greet(name = 'World'):
    print('Hello '+name)

greet(name = 'Praveen')
greet()

来自评论中链接的这个问题:How to know if optparse option was passed in the command line or as a default

我能够在 SCons 中将其用于我的案例:

from SCons.Environment import Environment
from SCons.Script.SConsOptions import Parser

###################################################
# Determine number of Jobs
# start by assuming num_jobs was not set
opts_no_defaults = optparse.Values()
parser = Parser(MAIN_ENV._get_major_minor_revision(SCons.__version__))
__, args = parser.parse_args(values=opts_no_defaults)
opts = optparse.Values(parser.get_default_values().__dict__)
opts._update_careful(opts_no_defaults.__dict__)

# num_jobs wasn't specificed so let use the
# max number since the user doesn't seem to care
if not hasattr(opts_no_defaults, parser.get_option('--jobs').dest):
    NUM_CPUS = get_num_cpus()
    ColorPrinter().InfoPrint("Building with " + str(NUM_CPUS) + " parallel jobs")
    MAIN_ENV.SetOption("num_jobs", NUM_CPUS)
else:
    # user wants a certain number of jobs so do that
    ColorPrinter().InfoPrint(
        "Building with " + str(GetOption('num_jobs')) + " parallel jobs")