16

我已经使用 optparse 一段时间了,并且想添加从配置文件加载参数的功能。

到目前为止,我能想到的最好的是带有硬编码参数的包装批处理脚本......看起来很笨重。

最优雅的方法是什么?

4

6 回答 6

23

我同意 S.Lott 使用配置文件的想法,但我建议使用内置的ConfigParser(3.0 中的 configparser)模块来解析它,而不是自制的解决方案。

这是一个简短的脚本,说明了 ConfigParser 和optparse的作用。

import ConfigParser
from optparse import OptionParser

CONFIG_FILENAME = 'defaults.cfg'

def main():
    config = ConfigParser.ConfigParser()
    config.read(CONFIG_FILENAME)

    parser = OptionParser()
    parser.add_option("-l",
                      "--language",
                      dest="language",
                      help="The UI language",
                      default=config.get("Localization", "language"))
    parser.add_option("-f",
                      "--flag",
                      dest="flag",
                      help="The country flag",
                      default=config.get("Localization", "flag"))

    print parser.parse_args()

if __name__ == "__main__":
    main()

输出:

(<Values at 0x2182c88: {'flag': 'japan.png', 'language': 'Japanese'}>, [])

使用“ parser.py --language=French”运行:

(<Values at 0x2215c60: {'flag': 'japan.png', 'language': 'French'}>, [])

帮助是内置的。使用“ parser.py --help”运行:

Usage: parser.py [options]

Options:
  -h, --help            show this help message and exit
  -l LANGUAGE, --language=LANGUAGE
                        The UI language
  -f FLAG, --flag=FLAG  The country flag

配置文件:

[Localization]
language=Japanese
flag=japan.png
于 2009-12-10T12:23:42.620 回答
7

您可以argparse为此使用模块:

>>> open('args.txt', 'w').write('-f\nbar')
>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
>>> parser.add_argument('-f')
>>> parser.parse_args(['-f', 'foo', '@args.txt'])
Namespace(f='bar')

它可能包含在 stdlib 中,请参阅pep 389

于 2009-12-10T21:00:38.393 回答
4

我有一个类似的问题,但也想将配置文件指定为参数。受 S. Lott 回答的启发,我想出了以下代码。

终端会话示例:

$ python defaultconf.py # 使用硬编码的默认值
错误的
$ python defaultconf.py --verbose # 命令行详细
真的
$ python defaultconf.py --loadconfig blah # 加载配置 'verbose':True
真的
$ python defaultconf.py --loadconfig blah --quiet # 覆盖配置值
错误的

代码:

#!/usr/bin/env python2.6
import optparse

def getParser(defaults):
    """Create and return an OptionParser instance, with supplied defaults
    """
    o = optparse.OptionParser()
    o.set_defaults(**defaults)
    o.add_option("--verbose", dest = "verbose", action="store_true")
    o.add_option("--quiet", dest = "verbose", action="store_false")

    o.add_option("--loadconfig", dest = "loadconfig")

    return o


def main():
    # Hard coded defaults (including non-command-line-argument options)
    my_defaults = {'verbose': False, 'config_only_variable': 42}

    # Initially parse arguments
    opts, args = getParser(my_defaults).parse_args()

    if opts.loadconfig is not None:
        # Load config from disk, update the defaults dictionary, and reparse
        # Could use ConfigParser, simplejson, yaml etc.

        config_file_values = {'verbose': True} # the dict loaded from disk

        my_defaults.update(config_file_values)
        opts, args = getParser(my_defaults).parse_args()

    print opts.verbose

if __name__ == '__main__':
    main()

一个实用的实现可以在 Github 上找到:默认字典参数解析器主函数

于 2010-02-05T22:59:12.913 回答
3

这就是set_defaults函数的用途。 http://docs.python.org/library/optparse.html#optparse.OptionParser.set_defaults

创建一个作为默认值字典的文件。

{ 'arg1': 'this',
'arg2': 'that'
}

然后读取此文件,对其进行评估以将文本转换为字典,并将此字典作为参数提供给set_defaults.

如果您真的很担心eval,请为此文件使用 JSON(或 YAML)表示法。或者你甚至可以用.INI它制作一个文件并configparser用来获取你的默认值。

或者,您可以使用简单的赋值语句列表和exec.

配置文件。

arg1 = 'this'
arg2 = 'that'

读取配置文件。

defaults= {}
with open('defaults.py','r') as config
    exec config in {}, defaults
于 2009-12-10T11:40:56.217 回答
2

从文件(例如@commands)中以相同的命令行格式读取参数,然后使用您的原始解析器来解析它们。

options, args = parser.parse_args()

if args[0][0] == '@': # script.py @optfile 
    with open(args[0][1:]) as f:
        fa = [l.strip() for l in f]
    fa = fa + args[1:] # put back any other positional arguments
    # Use your original parser to parse the new options
    options, args = parser.parse_args(args=fa, values=options)
于 2011-07-11T21:57:59.403 回答
0

我最近构建了很多带有标志和选项的脚本,并且我想出了这里描述的解决方案。

基本上,我实例化了一个带有特殊标志的选项解析器,该标志告诉尝试从文件中加载选项,因此您可以正常使用脚本从命令行指定选项或从文件中提供它们(或一组)。

更新:我在GitHub 上共享了代码

于 2011-10-13T14:06:45.353 回答