小编典典

哪一种是允许在Python命令行中覆盖配置选项的最佳方法?

python

我有一个需要大量(〜30)配置参数的Python应用程序。到目前为止,我使用OptionParser类在应用程序本身中定义默认值,并且可以在调用应用程序时在命令行上更改单个参数。

现在,我想使用“适当的”配置文件,例如ConfigParser类中的文件。同时,用户仍然应该能够在命令行上更改单个参数。

我想知道是否有任何方法可以将两个步骤结合起来,例如使用optparse(或较新的argparse)来处理命令行选项,但是要以ConfigParse语法从配置文件中读取默认值。

有什么想法如何轻松地做到这一点?我不太喜欢手动调用ConfigParse,然后手动将所有选项的所有默认值设置为适当的值…


阅读 204

收藏
2021-01-20

共1个答案

小编典典

我刚刚发现您可以使用argparse.ArgumentParser.parse_known_args()。首先使用parse_known_args()从命令行解析配置文件,然后使用ConfigParser读取配置文件并设置默认值,然后使用解析其余的选项parse_args()。这将使您拥有一个默认值,使用配置文件覆盖它,然后使用命令行选项覆盖它。例如:

默认,无用户输入:

$ ./argparse-partial.py
Option is "default"

配置文件中的默认值:

$ cat argparse-partial.config 
[Defaults]
option=Hello world!
$ ./argparse-partial.py -c argparse-partial.config 
Option is "Hello world!"

配置文件中的默认值,被命令行覆盖:

$ ./argparse-partial.py -c argparse-partial.config --option override
Option is "override"

接下来是argprase-partial.py。-h正确处理以获得帮助有些复杂。

import argparse
import ConfigParser
import sys

def main(argv=None):
    # Do argv default this way, as doing it in the functional
    # declaration sets it at compile time.
    if argv is None:
        argv = sys.argv

    # Parse any conf_file specification
    # We make this parser with add_help=False so that
    # it doesn't parse -h and print help.
    conf_parser = argparse.ArgumentParser(
        description=__doc__, # printed with -h/--help
        # Don't mess with format of description
        formatter_class=argparse.RawDescriptionHelpFormatter,
        # Turn off help, so we print all options in response to -h
        add_help=False
        )
    conf_parser.add_argument("-c", "--conf_file",
                        help="Specify config file", metavar="FILE")
    args, remaining_argv = conf_parser.parse_known_args()

    defaults = { "option":"default" }

    if args.conf_file:
        config = ConfigParser.SafeConfigParser()
        config.read([args.conf_file])
        defaults.update(dict(config.items("Defaults")))

    # Parse rest of arguments
    # Don't suppress add_help here so it will handle -h
    parser = argparse.ArgumentParser(
        # Inherit options from config_parser
        parents=[conf_parser]
        )
    parser.set_defaults(**defaults)
    parser.add_argument("--option")
    args = parser.parse_args(remaining_argv)
    print "Option is \"{}\"".format(args.option)
    return(0)

if __name__ == "__main__":
    sys.exit(main())
2021-01-20