如何使用反向轻松创建python argparse参数?

时间:2015-05-21 20:41:39

标签: python-3.x command-line-arguments argparse

在Python 3中使用argparse,我想创建一对互补的参数:

--log-file=~/some-default-log-filename.txt
--no-log-file

如示例所示,默认情况下,日志文件参数将具有默认值(文件名)。您可以通过为--log-file指定不同的字符串值来更改它,或者通过指定--no-log-file来完全删除日志文件。

在argparse中执行此操作的优雅方法是什么?我根本无法找到任何反向/互补参数的方法,也不介意有一个字符串参数的位置。

最好的情况是,当我执行args = parser.parse_args()时,args.log_file包含日志文件名(包括默认名称)或None如果no-log-file选项已包含指定。

2 个答案:

答案 0 :(得分:3)

检查此结尾是否为基于store_const的解决方案。

我记得看到一个旧的python bug问题,建议使用一些可以自动处理argparse--foo以及其他一些变体的代码扩展--no-foo。也许我以后会发现。

但目前argparse没有符合您规范的机制。

nargs='?' constdefault旨在处理与您相同的3倍案例。

# no --foo, assign the 'default'
--foo # without arg, assign the 'const'
--foo arg  # assign the supplied string

虽然语法不完全符合您的要求,但我认为它可以为您的用户提供相同的控制权。

为了更接近您想要的语法,您必须创建logfile参数和no-log参数,然后使用简单的pos解析测试来“合并”这两个参数。 / p>

parser.add_argument('--log-file', ....)
parser.add_argument('--no-log', action='store_true')

以后:

if args.no_log:
    args.log_file = None

如果你必须创建这样的许多参数对,你可以定义一个辅助函数:

def make_inverse_arg(parser, *args, **kwargs):
    parser.add_argument(*args, **kwargs)
    # define inverse
    arg1 = '--no-'+args[1][2:]
    parser.add_argument(arg1, action='store_true')
    # could be more robust, but you get the idea
    def post_test():
         ...
    return post_test

如果--no-foo被定义为'store_const'参数,const=None和dest --foo相同,则只有None存在于命名空间中。 default=SUPPRESS确保它不会将自己的默认值放入命名空间。

parser=argparse.ArgumentParser()
parser.add_argument('--no-foo', dest='foo', action='store_const', const=None,
     default=argparse.SUPPRESS)
parser.add_argument('--foo',default='test')

In [329]: parser.parse_args([])
Out[329]: Namespace(foo='test')

In [330]: parser.parse_args('--foo xxx'.split())
Out[330]: Namespace(foo='xxx')

In [331]: parser.parse_args('--foo xxx --no-foo'.split())
Out[331]: Namespace(foo=None)

In [332]: parser.parse_args('--no-foo --foo xxx'.split())
Out[332]: Namespace(foo='xxx')

In [333]: parser.parse_args('--no-foo'.split())
Out[333]: Namespace(foo=None)

如果存在冲突,则--foo--no-foo的最后一个确定命名空间中的内容。

答案 1 :(得分:2)

它不是相当您正在寻找的东西,但我会这样做:

parser.add_argument(
    "--log-file", 
    const="~/some-default-log-filename.txt", 
    default=None,
    dest="log_file",
    nargs="?"
)

这处理三种情况:

  • ... --log-file mylog.txt ... - 登录到用户指定的文件;
  • ... --log-file ... - 登录const默认文件;和
  • ... - 使用defaultNone

有关详细信息,请参阅the docs on nargs