首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何避免在省略参数时出现argparser类型错误?

如何避免在省略参数时出现argparser类型错误?
EN

Stack Overflow用户
提问于 2020-07-29 01:30:21
回答 1查看 266关注 0票数 1

在R中使用argparser时,当在对add_argument的调用中指定参数的类型,但没有在MacOSX命令行将参数传递给脚本时,我得到了一个错误。例如,给定这个R脚本:

代码语言:javascript
代码运行次数:0
运行
复制
library(argparser)
p <- arg_parser(description = "A test parser")
p <- add_argument(p, "--alpha", type = "double", help = "alpha for p-value")
p <- add_argument(p, "--sig-digits", type = "integer", help="number of significant digits")
args <- parse_args(p)
print(str(args))

并在命令行中调用它:

代码语言:javascript
代码运行次数:0
运行
复制
Rscript argparser-test.R --alpha 0.1

我得到的结果是:

代码语言:javascript
代码运行次数:0
运行
复制
Error in (function (object, class, nargs)  :
Invalid argument value: expecting integer but got: (NA).
Calls: parse_args -> mapply -> <Anonymous>

有趣的是,如果让--alpha接受它的默认值,就不会出现错误:

代码语言:javascript
代码运行次数:0
运行
复制
Rscript argparser-test.R

返回:

代码语言:javascript
代码运行次数:0
运行
复制
List of 5
 $           : logi FALSE
 $ help      : logi FALSE
 $ opts      : logi NA
 $ alpha     : logi NA
 $ sig_digits: logi NA
NULL

注意,这里sig_digitsNA值是logical类型,而不是add_argument函数中定义的integer类型。

我是不是做错了什么?同时,我想我可以通过设置默认的--sig-digits = -1来解决这个问题,然后将其作为异常处理,但我不希望这样做。

更新:实际上,-1抛出了同样的错误,这是非常令人沮丧的,因为我想使用一个数字来表示没有意义的异常。9999可以工作,不太可能由用户输入,但实际上它是有效的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-29 01:38:42

大约一个月前,我经历了这个错误。这是argparser包如何解析可选参数的问题。基本上,它确实尊重可选参数的顺序,因为它在每种情况下都应该这样做,有时它会因此期望错误的参数类型。

我已经在package bitbucket页面上打开了一个issue。我强烈建议提升这一点,并添加一个评论,以帮助增加对该问题的关注。

在我的问题中,我为这个问题提供了一个可能的解决方案,它相当于将parse_args更改为以下定义(您可以使用此函数拉出并重新创建包,在这一点上,它将按预期工作)

代码语言:javascript
代码运行次数:0
运行
复制
parse_args <- function (parser, argv = commandArgs(trailingOnly = TRUE)) 
{
    stopifnot(is(parser, "arg.parser"))
    values <- list()
    argv <- preprocess_argv(argv, parser)
    arg.flags <- parser$args[parser$is.flag]
    x <- as.logical(parser$defaults[parser$is.flag])
    x[is.na(x)] <- FALSE
    names(x) <- sub("^-+", "", arg.flags)
    flag.idx <- match(arg.flags, argv)
    flag.idx <- flag.idx[!is.na(flag.idx)]
    if (length(flag.idx) > 0) {
        x[match(argv[flag.idx], arg.flags)] <- TRUE
        argv <- argv[-flag.idx]
    }
    values <- c(values, x)
    if (values$help) {
        print(parser)
        quit()
    }
    x <- parser$defaults[parser$is.opt.arg]
    arg.opt <- parser$args[parser$is.opt.arg]
    names(x) <- sub("^-+", "", arg.opt)
    i <- match("--opts", argv)
    if (!is.na(i)) {
        opts <- readRDS(argv[i + 1])
        opts <- opts[!names(opts) %in% c("opts", "help")]
        idx <- match(sanitize_arg_names(names(opts)), sanitize_arg_names(names(x)))
        if (any(is.na(idx))) {
            stop("Extra arguments supplied in OPTS file: (", 
                paste(setdiff(names(opts), names(x)), collapse = ", "), 
                ").")
        }
        x[idx] <- opts
    }
    arg.idx <- match(arg.opt, argv)
    arg.idx <- arg.idx[!is.na(arg.idx)]
    arg.opt.types <- parser$types[parser$is.opt.arg]
    arg.opt.nargs <- parser$nargs[parser$is.opt.arg]
    ###               ###
    ## Altered section ##
    ###               ###
    if (length(arg.idx) > 0) {
        # extract values following the optional argument label
        x[ind <- match(argv[arg.idx], arg.opt)] <- argv[arg.idx+1];
        # convert type of extraced values; x is now a list
        x[ind] <- mapply(convert_type,                                
                         object = x[ind], 
                         class = arg.opt.types[ind], 
                         nargs = arg.opt.nargs[ind], 
                         SIMPLIFY = FALSE);                                    
        # remove extracted arguments
        to.remove <- c(arg.idx, arg.idx+1);
        argv <- argv[-to.remove];
    }
    ###               ###
    ## Altered section ##
    ###               ###
    values <- c(values, x)
    x <- argv
    args.req <- parser$args[parser$is.req.arg]
    args.req.types <- parser$types[parser$is.req.arg]
    args.req.nargs <- parser$nargs[parser$is.req.arg]
    if (length(x) < length(args.req)) {
        print(parser)
        stop(sprintf("Missing required arguments: expecting %d values but got %d values: (%s).", 
            length(args.req), length(x), paste(x, collapse = ", ")))
    }
    else if (length(x) > length(args.req)) {
        print(parser)
        stop(sprintf("Extra arguments supplied: expecting %d values but got %d values: (%s).", 
            length(args.req), length(x), paste(x, collapse = ", ")))
    }
    else if (length(args.req) > 0) {
        names(x) <- args.req
        x <- mapply(convert_type, object = x, class = args.req.types, 
            nargs = args.req.nargs, SIMPLIFY = FALSE)
    }
    values <- c(values, x)
    names(values) <- sanitize_arg_names(names(values))
    values
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63139686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档