1. ホーム
  2. python

[解決済み] Pythonでコマンドラインから設定オプションを上書きできるようにするには、どの方法が一番良いですか?

2023-01-20 02:13:05

質問

私は、かなり多くの(〜30)設定パラメータを必要とするPythonアプリケーションを持っています。これまで、私はアプリケーション自体のデフォルト値を定義するためにOptionParserクラスを使用し、アプリケーションを起動するときにコマンドラインで個々のパラメータを変更する可能性を持っていました。

今、私は、例えばConfigParserクラスからの「適切な」設定ファイルを使いたいと考えています。同時に、ユーザーはコマンドラインで個々のパラメーターを変更できるようにする必要があります。

例えば、コマンドライン オプションを処理するために optparse (または新しい argparse) を使用しますが、ConfigParse 構文で設定ファイルからデフォルト値を読み取るなど、2 つのステップを組み合わせる方法があるかどうか疑問に思っていました。

これを簡単に行う方法について何かアイデアはありますか?手動で ConfigParse を呼び出して、すべてのオプションのデフォルトを適切な値に手動で設定するのは、あまり気が進みません...。

どのように解決するのですか?

私はちょうどあなたがこれを行うことができます発見した 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())