programing

구성 파일, 환경 및 명령줄 인수를 구문 분석하여 단일 옵션 모음을 가져옵니다.

sourcejob 2023. 7. 28. 21:58
반응형

구성 파일, 환경 및 명령줄 인수를 구문 분석하여 단일 옵션 모음을 가져옵니다.

Python의 표준 라이브러리에는 구성 파일 구문 분석(configparser), 환경 변수 읽기(os.environ) 및 명령줄 인수 구문 분석(argparse)을 위한 모듈이 있습니다.저는 이 모든 것을 할 수 있는 프로그램을 만들고 싶습니다. 또한 다음과 같습니다.

  • 일련의 옵션 값이 있습니다.

    • 기본 옵션 값, 재정의됨
    • 구성 파일 옵션, 재정의됨
    • 환경 변수, 재정의됨
    • 명령줄 옵션.
  • 예를 들어 명령줄에 하나 이상의 구성 파일 위치를 지정할 수 있습니다.--config-file foo.conf(일반 구성 파일 대신 또는 일반 구성 파일에 추가)를 읽습니다.이것은 여전히 위의 캐스케이드를 따라야 합니다.

  • 단일 위치에서 옵션 정의를 통해 구성 파일 및 명령줄에 대한 구문 분석 동작을 결정할 수 있습니다.

  • 구문 분석된 옵션을 단일 옵션모음으로 통합하여 프로그램의 나머지 부분이 어디서 왔는지 상관없이 액세스할 수 있도록 합니다.

제가 필요한 모든 것이 파이썬 표준 라이브러리에 있는 것처럼 보이지만, 서로 원활하게 작동하지 않습니다.

Python 표준 라이브러리에서 최소 편차로 이를 달성하려면 어떻게 해야 합니까?

업데이트: 저는 마침내 이것을 파이피에 올릴 수 있게 되었습니다.다음을 통해 최신 버전 설치:

   pip install configargparser

전체 도움말지침이 여기에 있습니다.

원본 게시물

여기 제가 함께 해킹한 작은 것이 있습니다.의견에 대한 개선 사항/버그 보고서를 자유롭게 제안하십시오.

import argparse
import ConfigParser
import os

def _identity(x):
    return x

_SENTINEL = object()


class AddConfigFile(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        # I can never remember if `values` is a list all the time or if it
        # can be a scalar string; this takes care of both.
        if isinstance(values,basestring):
            parser.config_files.append(values)
        else:
            parser.config_files.extend(values)


class ArgumentConfigEnvParser(argparse.ArgumentParser):
    def __init__(self,*args,**kwargs):
        """
        Added 2 new keyword arguments to the ArgumentParser constructor:

           config --> List of filenames to parse for config goodness
           default_section --> name of the default section in the config file
        """
        self.config_files = kwargs.pop('config',[])  #Must be a list
        self.default_section = kwargs.pop('default_section','MAIN')
        self._action_defaults = {}
        argparse.ArgumentParser.__init__(self,*args,**kwargs)


    def add_argument(self,*args,**kwargs):
        """
        Works like `ArgumentParser.add_argument`, except that we've added an action:

           config: add a config file to the parser

        This also adds the ability to specify which section of the config file to pull the 
        data from, via the `section` keyword.  This relies on the (undocumented) fact that
        `ArgumentParser.add_argument` actually returns the `Action` object that it creates.
        We need this to reliably get `dest` (although we could probably write a simple
        function to do this for us).
        """

        if 'action' in kwargs and kwargs['action'] == 'config':
            kwargs['action'] = AddConfigFile
            kwargs['default'] = argparse.SUPPRESS

        # argparse won't know what to do with the section, so 
        # we'll pop it out and add it back in later.
        #
        # We also have to prevent argparse from doing any type conversion,
        # which is done explicitly in parse_known_args.  
        #
        # This way, we can reliably check whether argparse has replaced the default.
        #
        section = kwargs.pop('section', self.default_section)
        type = kwargs.pop('type', _identity)
        default = kwargs.pop('default', _SENTINEL)

        if default is not argparse.SUPPRESS:
            kwargs.update(default=_SENTINEL)
        else:  
            kwargs.update(default=argparse.SUPPRESS)

        action = argparse.ArgumentParser.add_argument(self,*args,**kwargs)
        kwargs.update(section=section, type=type, default=default)
        self._action_defaults[action.dest] = (args,kwargs)
        return action

    def parse_known_args(self,args=None, namespace=None):
        # `parse_args` calls `parse_known_args`, so we should be okay with this...
        ns, argv = argparse.ArgumentParser.parse_known_args(self, args=args, namespace=namespace)
        config_parser = ConfigParser.SafeConfigParser()
        config_files = [os.path.expanduser(os.path.expandvars(x)) for x in self.config_files]
        config_parser.read(config_files)

        for dest,(args,init_dict) in self._action_defaults.items():
            type_converter = init_dict['type']
            default = init_dict['default']
            obj = default

            if getattr(ns,dest,_SENTINEL) is not _SENTINEL: # found on command line
                obj = getattr(ns,dest)
            else: # not found on commandline
                try:  # get from config file
                    obj = config_parser.get(init_dict['section'],dest)
                except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): # Nope, not in config file
                    try: # get from environment
                        obj = os.environ[dest.upper()]
                    except KeyError:
                        pass

            if obj is _SENTINEL:
                setattr(ns,dest,None)
            elif obj is argparse.SUPPRESS:
                pass
            else:
                setattr(ns,dest,type_converter(obj))

        return ns, argv


if __name__ == '__main__':
    fake_config = """
[MAIN]
foo:bar
bar:1
"""
    with open('_config.file','w') as fout:
        fout.write(fake_config)

    parser = ArgumentConfigEnvParser()
    parser.add_argument('--config-file', action='config', help="location of config file")
    parser.add_argument('--foo', type=str, action='store', default="grape", help="don't know what foo does ...")
    parser.add_argument('--bar', type=int, default=7, action='store', help="This is an integer (I hope)")
    parser.add_argument('--baz', type=float, action='store', help="This is an float(I hope)")
    parser.add_argument('--qux', type=int, default='6', action='store', help="this is another int")
    ns = parser.parse_args([])

    parser_defaults = {'foo':"grape",'bar':7,'baz':None,'qux':6}
    config_defaults = {'foo':'bar','bar':1}
    env_defaults = {"baz":3.14159}

    # This should be the defaults we gave the parser
    print ns
    assert ns.__dict__ == parser_defaults

    # This should be the defaults we gave the parser + config defaults
    d = parser_defaults.copy()
    d.update(config_defaults)
    ns = parser.parse_args(['--config-file','_config.file'])
    print ns
    assert ns.__dict__ == d

    os.environ['BAZ'] = "3.14159"

    # This should be the parser defaults + config defaults + env_defaults
    d = parser_defaults.copy()
    d.update(config_defaults)
    d.update(env_defaults)
    ns = parser.parse_args(['--config-file','_config.file'])
    print ns
    assert ns.__dict__ == d

    # This should be the parser defaults + config defaults + env_defaults + commandline
    commandline = {'foo':'3','qux':4} 
    d = parser_defaults.copy()
    d.update(config_defaults)
    d.update(env_defaults)
    d.update(commandline)
    ns = parser.parse_args(['--config-file','_config.file','--foo=3','--qux=4'])
    print ns
    assert ns.__dict__ == d

    os.remove('_config.file')

하기 위해서

이 구현은 아직 완료되지 않았습니다.다음은 TODO의 일부 목록입니다.

  • (쉬운) 파서 기본값과의 상호 작용
  • how와 합니다.argparse오류 메시지 처리

문서화된 동작 준수

  • ▁(▁out▁▁figures다▁(를 구하는 함수를 씁니다.destargsadd_argument에의하대에신는존▁▁on에 의존하는 Action
  • (간단함쓰기)기)parse_args을사하기능을 사용하는 parse_known_args copy (예: 복사예)parse_argscpython그것이 요구하는 것을 보장하기 위한 실행.parse_known_args.)

쉬운 것을 덜…

저는 아직 이거 하나도 안 먹어봤어요.그럴 것 같지는 않지만 그래도 가능합니다!효과적일 수 있다는 것...

  • (어려운가요?) 상호 제외
  • (어려운가요?) 인수 그룹(구현된 경우, 이러한 그룹은 다음을 얻어야 합니다.section구성 파일에 포함됩니다.)
  • (어려운가요?) 하위 명령(하위 명령도 다음 값을 얻어야 합니다.section구성 파일에 포함됩니다.)

argparse 모듈은 명령행처럼 보이는 구성 파일에 만족하는 한 이것을 미친 것처럼 만들지 않습니다.(사용자는 하나의 구문만 배우면 되기 때문에 이것이 장점이라고 생각합니다.file_prefix_chars에서 예를 들어,@ 음과같합니다다이다.

my_prog --foo=bar

와 동등합니다.

my_prog @baz.conf

한다면@baz.conf 사실은,

--foo
bar

코드를 검색할 수도 있습니다.foo.conf수하여자를 수정하여 argv

if os.path.exists('foo.conf'):
    argv = ['@foo.conf'] + argv
args = argparser.parse_args(argv)

이러한 구성 파일의 형식은 ArgumentParser의 하위 클래스를 만들고 convert_arg_line_to_args 메서드를 추가하여 수정할 수 있습니다.

직접 해보지는 않았지만, 사용자가 원하는 대부분의 작업을 수행한다는 ConfigArgParse 라이브러리가 있습니다.

구성 파일 및/또는 환경 변수를 통해 옵션을 설정할 수 있는 Argparse에 대한 드롭인 대체 기능입니다.

configglue라고 불리는 라이브러리가 있습니다.

configglue는 python의 opparse를 접착제로 사용하는 라이브러리입니다.옵션 분석기 및 구성 분석기.구성 파일 및 명령줄 인터페이스로 동일한 옵션을 내보낼 때 반복하지 않도록 파서를 구성합니다.

또한 환경 변수도 지원합니다.

ConfigArgParse라는 다른 라이브러리도 있습니다.

구성 파일 및/또는 환경 변수를 통해 옵션을 설정할 수 있는 Argparse에 대한 드롭인 대체 기능입니다.

PyCon이 Wukasz Langa - Let Them Configure!의 구성에 대해 이야기하는 것에 관심이 있을 수 있습니다.

문제를 각 합니다.configparser그리고.argparse그리고.os.environ모두 함께 투박한 방식으로.

이러한 모든 요구 사항을 충족하려면 기본 기능에 [opt|arg]parse와 configparser를 모두 사용하는 라이브러리를 작성하는 것이 좋습니다.

처음 두 가지와 마지막 요구 사항을 고려할 때, 당신은 다음을 원한다고 말할 수 있습니다.

1단계: --config-file 옵션만 찾는 명령줄 파서 패스를 수행합니다.

2단계: 구성 파일을 구문 분석합니다.

3단계: 구성 파일 패스의 출력을 기본값으로 사용하여 두 번째 명령줄 파서 패스를 설정합니다.

세 번째 요구 사항은 당신이 관심 있는 optparse 및 configparser의 모든 기능을 노출하고 그 사이에 변환을 수행할 배관을 작성하도록 당신 자신의 옵션 정의 시스템을 설계해야 한다는 것을 의미합니다.

Python 표준 라이브러리는 이것을 제공하지 않는 것으로 알고 있습니다.사용할 코드를 작성하여 직접 해결했습니다.optparse그리고.ConfigParser명령줄 및 구성 파일을 구문 분석하고 그 위에 추상화 계층을 제공합니다.하지만, 당신은 이것이 별도의 의존성으로 필요할 것이며, 이것은 당신의 이전 논평에서 불쾌해 보입니다.

제가 작성한 코드를 보시려면 http://liw.fi/cliapp/ 에 있습니다.이 기능은 "명령줄 애플리케이션 프레임워크" 라이브러리에 통합되어 있습니다. 이는 프레임워크가 수행해야 하는 작업의 상당 부분이기 때문입니다.

저는 최근에 "optparse"를 사용하여 이런 시도를 받았습니다.

'--Store' 및 '--Check' 명령을 사용하여 OptonParser의 하위 클래스로 설정했습니다.

아래의 코드는 당신이 거의 다 다루었을 것입니다.사전을 승인/반환하는 고유한 '로드' 및 '저장' 방법을 정의하기만 하면 됩니다.


class SmartParse(optparse.OptionParser):
    def __init__(self,defaults,*args,**kwargs):
        self.smartDefaults=defaults
        optparse.OptionParser.__init__(self,*args,**kwargs)
        fileGroup = optparse.OptionGroup(self,'handle stored defaults')
        fileGroup.add_option(
            '-S','--Store',
            dest='Action',
            action='store_const',const='Store',
            help='store command line settings'
        )
        fileGroup.add_option(
            '-C','--Check',
            dest='Action',
            action='store_const',const='Check',
            help ='check stored settings'
        )
        self.add_option_group(fileGroup)
    def parse_args(self,*args,**kwargs):
        (options,arguments) = optparse.OptionParser.parse_args(self,*args,**kwargs)
        action = options.__dict__.pop('Action')
        if action == 'Check':
            assert all(
                value is None 
                for (key,value) in options.__dict__.iteritems() 
            )
            print 'defaults:',self.smartDefaults
            print 'config:',self.load()
            sys.exit()
        elif action == 'Store':
            self.store(options.__dict__)
            sys.exit()
        else:
            config=self.load()
            commandline=dict(
                [key,val] 
                for (key,val) in options.__dict__.iteritems() 
                if val is not None
            )
            result = {}
            result.update(self.defaults)
            result.update(config)
            result.update(commandline)
            return result,arguments
    def load(self):
        return {}
    def store(self,optionDict):
        print 'Storing:',optionDict

여기 제가 함께 해킹한 모듈이 있습니다. 명령줄 인수, 환경 설정, ini 파일 및 키링 값도 읽습니다.그것은 요지로도 이용 가능합니다.

"""
Configuration Parser

Configurable parser that will parse config files, environment variables,
keyring, and command-line arguments.



Example test.ini file:

    [defaults]
    gini=10

    [app]
    xini = 50

Example test.arg file:

    --xfarg=30

Example test.py file:

    import os
    import sys

    import config


    def main(argv):
        '''Test.'''
        options = [
            config.Option("xpos",
                          help="positional argument",
                          nargs='?',
                          default="all",
                          env="APP_XPOS"),
            config.Option("--xarg",
                          help="optional argument",
                          default=1,
                          type=int,
                          env="APP_XARG"),
            config.Option("--xenv",
                          help="environment argument",
                          default=1,
                          type=int,
                          env="APP_XENV"),
            config.Option("--xfarg",
                          help="@file argument",
                          default=1,
                          type=int,
                          env="APP_XFARG"),
            config.Option("--xini",
                          help="ini argument",
                          default=1,
                          type=int,
                          ini_section="app",
                          env="APP_XINI"),
            config.Option("--gini",
                          help="global ini argument",
                          default=1,
                          type=int,
                          env="APP_GINI"),
            config.Option("--karg",
                          help="secret keyring arg",
                          default=-1,
                          type=int),
        ]
        ini_file_paths = [
            '/etc/default/app.ini',
            os.path.join(os.path.dirname(os.path.abspath(__file__)),
                         'test.ini')
        ]

        # default usage
        conf = config.Config(prog='app', options=options,
                             ini_paths=ini_file_paths)
        conf.parse()
        print conf

        # advanced usage
        cli_args = conf.parse_cli(argv=argv)
        env = conf.parse_env()
        secrets = conf.parse_keyring(namespace="app")
        ini = conf.parse_ini(ini_file_paths)
        sources = {}
        if ini:
            for key, value in ini.iteritems():
                conf[key] = value
                sources[key] = "ini-file"
        if secrets:
            for key, value in secrets.iteritems():
                conf[key] = value
                sources[key] = "keyring"
        if env:
            for key, value in env.iteritems():
                conf[key] = value
                sources[key] = "environment"
        if cli_args:
            for key, value in cli_args.iteritems():
                conf[key] = value
                sources[key] = "command-line"
        print '\n'.join(['%s:\t%s' % (k, v) for k, v in sources.items()])


    if __name__ == "__main__":
        if config.keyring:
            config.keyring.set_password("app", "karg", "13")
        main(sys.argv)

Example results:

    $APP_XENV=10 python test.py api --xarg=2 @test.arg
    <Config xpos=api, gini=1, xenv=10, xini=50, karg=13, xarg=2, xfarg=30>
    xpos:   command-line
    xenv:   environment
    xini:   ini-file
    karg:   keyring
    xarg:   command-line
    xfarg:  command-line


"""
import argparse
import ConfigParser
import copy
import os
import sys

try:
    import keyring
except ImportError:
    keyring = None


class Option(object):
    """Holds a configuration option and the names and locations for it.

    Instantiate options using the same arguments as you would for an
    add_arguments call in argparse. However, you have two additional kwargs
    available:

        env: the name of the environment variable to use for this option
        ini_section: the ini file section to look this value up from
    """

    def __init__(self, *args, **kwargs):
        self.args = args or []
        self.kwargs = kwargs or {}

    def add_argument(self, parser, **override_kwargs):
        """Add an option to a an argparse parser."""
        kwargs = {}
        if self.kwargs:
            kwargs = copy.copy(self.kwargs)
            try:
                del kwargs['env']
            except KeyError:
                pass
            try:
                del kwargs['ini_section']
            except KeyError:
                pass
        kwargs.update(override_kwargs)
        parser.add_argument(*self.args, **kwargs)

    @property
    def type(self):
        """The type of the option.

        Should be a callable to parse options.
        """
        return self.kwargs.get("type", str)

    @property
    def name(self):
        """The name of the option as determined from the args."""
        for arg in self.args:
            if arg.startswith("--"):
                return arg[2:].replace("-", "_")
            elif arg.startswith("-"):
                continue
            else:
                return arg.replace("-", "_")

    @property
    def default(self):
        """The default for the option."""
        return self.kwargs.get("default")


class Config(object):
    """Parses configuration sources."""

    def __init__(self, options=None, ini_paths=None, **parser_kwargs):
        """Initialize with list of options.

        :param ini_paths: optional paths to ini files to look up values from
        :param parser_kwargs: kwargs used to init argparse parsers.
        """
        self._parser_kwargs = parser_kwargs or {}
        self._ini_paths = ini_paths or []
        self._options = copy.copy(options) or []
        self._values = {option.name: option.default
                        for option in self._options}
        self._parser = argparse.ArgumentParser(**parser_kwargs)
        self.pass_thru_args = []

    @property
    def prog(self):
        """Program name."""
        return self._parser.prog

    def __getitem__(self, key):
        return self._values[key]

    def __setitem__(self, key, value):
        self._values[key] = value

    def __delitem__(self, key):
        del self._values[key]

    def __contains__(self, key):
        return key in self._values

    def __iter__(self):
        return iter(self._values)

    def __len__(self):
        return len(self._values)

    def get(self, key, *args):
        """
        Return the value for key if it exists otherwise the default.
        """
        return self._values.get(key, *args)

    def __getattr__(self, attr):
        if attr in self._values:
            return self._values[attr]
        else:
            raise AttributeError("'config' object has no attribute '%s'"
                                 % attr)

    def build_parser(self, options, **override_kwargs):
        """."""
        kwargs = copy.copy(self._parser_kwargs)
        kwargs.update(override_kwargs)
        if 'fromfile_prefix_chars' not in kwargs:
            kwargs['fromfile_prefix_chars'] = '@'
        parser = argparse.ArgumentParser(**kwargs)
        if options:
            for option in options:
                option.add_argument(parser)
        return parser

    def parse_cli(self, argv=None):
        """Parse command-line arguments into values."""
        if not argv:
            argv = sys.argv
        options = []
        for option in self._options:
            temp = Option(*option.args, **option.kwargs)
            temp.kwargs['default'] = argparse.SUPPRESS
            options.append(temp)
        parser = self.build_parser(options=options)
        parsed, extras = parser.parse_known_args(argv[1:])
        if extras:
            valid, pass_thru = self.parse_passthru_args(argv[1:])
            parsed, extras = parser.parse_known_args(valid)
            if extras:
                raise AttributeError("Unrecognized arguments: %s" %
                                     ' ,'.join(extras))
            self.pass_thru_args = pass_thru + extras
        return vars(parsed)

    def parse_env(self):
        results = {}
        for option in self._options:
            env_var = option.kwargs.get('env')
            if env_var and env_var in os.environ:
                value = os.environ[env_var]
                results[option.name] = option.type(value)
        return results

    def get_defaults(self):
        """Use argparse to determine and return dict of defaults."""
        parser = self.build_parser(options=self._options)
        parsed, _ = parser.parse_known_args([])
        return vars(parsed)

    def parse_ini(self, paths=None):
        """Parse config files and return configuration options.

        Expects array of files that are in ini format.
        :param paths: list of paths to files to parse (uses ConfigParse logic).
                      If not supplied, uses the ini_paths value supplied on
                      initialization.
        """
        results = {}
        config = ConfigParser.SafeConfigParser()
        config.read(paths or self._ini_paths)
        for option in self._options:
            ini_section = option.kwargs.get('ini_section')
            if ini_section:
                try:
                    value = config.get(ini_section, option.name)
                    results[option.name] = option.type(value)
                except ConfigParser.NoSectionError:
                    pass
        return results

    def parse_keyring(self, namespace=None):
        """."""
        results = {}
        if not keyring:
            return results
        if not namespace:
            namespace = self.prog
        for option in self._options:
            secret = keyring.get_password(namespace, option.name)
            if secret:
                results[option.name] = option.type(secret)
        return results

    def parse(self, argv=None):
        """."""
        defaults = self.get_defaults()
        args = self.parse_cli(argv=argv)
        env = self.parse_env()
        secrets = self.parse_keyring()
        ini = self.parse_ini()

        results = defaults
        results.update(ini)
        results.update(secrets)
        results.update(env)
        results.update(args)

        self._values = results
        return self

    @staticmethod
    def parse_passthru_args(argv):
        """Handles arguments to be passed thru to a subprocess using '--'.

        :returns: tuple of two lists; args and pass-thru-args
        """
        if '--' in argv:
            dashdash = argv.index("--")
            if dashdash == 0:
                return argv[1:], []
            elif dashdash > 0:
                return argv[0:dashdash], argv[dashdash + 1:]
        return argv, []

    def __repr__(self):
        return "<Config %s>" % ', '.join([
            '%s=%s' % (k, v) for k, v in self._values.iteritems()])


def comma_separated_strings(value):
    """Handles comma-separated arguments passed in command-line."""
    return map(str, value.split(","))


def comma_separated_pairs(value):
    """Handles comma-separated key/values passed in command-line."""
    pairs = value.split(",")
    results = {}
    for pair in pairs:
        key, pair_value = pair.split('=')
        results[key] = pair_value
    return results

ChainMap을 사용할 수 있습니다."Python의 명령줄에서 구성 옵션을 재정의할 수 있는 가장 좋은 방법은 무엇입니까?" 질문에서 제공한 예를 살펴 보십시오.

여기서 언급할 가치가 있는 것은 MIT 라이센스가 있고 PyPI에서 사용할 수 있는 jsonargparse입니다.구성 파일 및 환경 변수에서 로드를 지원하는 Argparse의 확장입니다.재정의 순서는 질문에서 질문한 것과 동일합니다(실제로는 이 순서의 상위 집합)

jsonargparse는 타사 라이브러리입니다.이 질문에는 "Python 표준 라이브러리의 최소 편차"가 표시되며, 이는 패키지를 설치할 필요가 없는 것으로 해석될 수 있습니다.여전히 이 질문을 읽는 많은 사람들은 타사 라이브러리를 사용하는 더 간단하고 깨끗한 솔루션을 사용해도 괜찮을 가능성이 높습니다.

»main.py다음과 같습니다.

from jsonargparse import ArgumentParser

parser = ArgumentParser(
    default_config_files=["defaults.yaml"],
    env_prefix="APP",
    default_env=True,
)
parser.add_argument("--opt1", default="code1")
parser.add_argument("--opt2", default="code2")
parser.add_argument("--opt3", default="code3")
parser.add_argument("--opt4", default="code4")
args = parser.parse_args()
print(args.opt1, args.opt2, args.opt3, args.opt4)

파일이 있는 경우defaults.yaml내용 포함:

opt2: defaults2

그런 다음 명령줄에서 예제를 실행합니다.

$ export APP_OPT3=env3
$ python main.py --opt4 arg4
code1 defaults2 env3 arg4

제가 만든 도서관 과자는 정확히 여러분의 요구를 충족시키기 위한 것입니다.

  • 지정된 파일 경로 또는 모듈 이름을 통해 구성 파일을 여러 번 로드할 수 있습니다.
  • 지정된 접두사를 사용하여 환경 변수에서 구성을 로드합니다.
  • 일부 클릭 명령에 명령줄 옵션을 연결할 수 있습니다.

    (죄송하지만, argarparse는 아니지만 click이 더 좋고 훨씬 더 고급입니다.confect향후 릴리스에서 argparse를 지원할 수 있음).

  • 가장 중요한 것은confectJSON/YMAL/TOML/INI가 아닌 Python 구성 파일을 로드합니다. IPython 프로필 파일 또는 DJANO 설정 파일과 마찬가지로 Python 구성 파일은 유연하고 유지 관리가 쉽습니다.

자세한 내용은 프로젝트 저장소의 README.rst를 확인하십시오.Python 3.6 이상만 지원합니다.

명령줄 옵션 연결

import click
from proj_X.core import conf

@click.command()
@conf.click_options
def cli():
    click.echo(f'cache_expire = {conf.api.cache_expire}')

if __name__ == '__main__':
    cli()

모든 속성과 기본값이 선언된 포괄적인 도움말 메시지가 자동으로 생성됩니다.

$ python -m proj_X.cli --help
Usage: cli.py [OPTIONS]

Options:
  --api-cache_expire INTEGER  [default: 86400]
  --api-cache_prefix TEXT     [default: proj_X_cache]
  --api-url_base_path TEXT    [default: api/v2/]
  --db-db_name TEXT           [default: proj_x]
  --db-username TEXT          [default: proj_x_admin]
  --db-password TEXT          [default: your_password]
  --db-host TEXT              [default: 127.0.0.1]
  --help                      Show this message and exit.

환경 변수 로드

환경 변수를 로드하려면 한 줄만 필요합니다.

conf.load_envvars('proj_X')

언급URL : https://stackoverflow.com/questions/6133517/parse-config-files-environment-and-command-line-arguments-to-get-a-single-col

반응형