【问题标题】:Python: How would you save a simple settings/config file?Python:你将如何保存一个简单的设置/配置文件?
【发布时间】:2013-10-05 08:51:15
【问题描述】:

我不在乎是 JSONpickleYAML 还是其他。

我见过的所有其他实现都不向前兼容,所以如果我有一个配置文件,在代码中添加一个新键,然后加载该配置文件,它就会崩溃。

有什么简单的方法吗?

【问题讨论】:

  • 我相信使用 configparser 模块的 .ini 类格式应该可以满足您的需求。
  • 有机会选择我的答案为正确吗?

标签: python json settings config ini


【解决方案1】:

保存并加载字典。您将拥有任意键、值和任意数量的键、值对。

【讨论】:

  • 我可以使用重构吗?
【解决方案2】:

如果您想使用类似 INI 文件的东西来保存设置,请考虑使用 configparser 从文本文件加载键值对,并且可以轻松地写回文件。

INI 文件格式为:

[Section]
key = value
key with spaces = somevalue

【讨论】:

    【解决方案3】:

    python中的配置文件

    根据所需的文件格式,有几种方法可以做到这一点。

    ConfigParser [.ini 格式]

    除非有令人信服的理由使用不同的格式,否则我会使用标准的 configparser 方法。

    像这样写一个文件:

    # python 2.x
    # from ConfigParser import SafeConfigParser
    # config = SafeConfigParser()
    
    # python 3.x
    from configparser import ConfigParser
    config = ConfigParser()
    
    config.read('config.ini')
    config.add_section('main')
    config.set('main', 'key1', 'value1')
    config.set('main', 'key2', 'value2')
    config.set('main', 'key3', 'value3')
    
    with open('config.ini', 'w') as f:
        config.write(f)
    

    文件格式非常简单,部分用方括号标出:

    [main]
    key1 = value1
    key2 = value2
    key3 = value3
    

    可以像这样从文件中提取值:

    # python 2.x
    # from ConfigParser import SafeConfigParser
    # config = SafeConfigParser()
    
    # python 3.x
    from configparser import ConfigParser
    config = ConfigParser()
    
    config.read('config.ini')
    
    print(config.get('main', 'key1')) # -> "value1"
    print(config.get('main', 'key2')) # -> "value2"
    print(config.get('main', 'key3')) # -> "value3"
    
    # getfloat() raises an exception if the value is not a float
    a_float = config.getfloat('main', 'a_float')
    
    # getint() and getboolean() also do this for their respective types
    an_int = config.getint('main', 'an_int')
    

    JSON [.json 格式]

    JSON 数据可能非常复杂,并且具有高度可移植性的优势。

    将数据写入文件:

    import json
    
    config = {"key1": "value1", "key2": "value2"}
    
    with open('config1.json', 'w') as f:
        json.dump(config, f)
    

    从文件中读取数据:

    import json
    
    with open('config.json', 'r') as f:
        config = json.load(f)
    
    #edit the data
    config['key3'] = 'value3'
    
    #write it back to the file
    with open('config.json', 'w') as f:
        json.dump(config, f)
    

    YAML

    in this answer 提供了一个基本的 YAML 示例。更多详情请访问the pyYAML website

    【讨论】:

    • 在python 3中from configparser import ConfigParserconfig = ConfigParser()
    【解决方案4】:

    ConfigParser 基本示例

    文件可以这样加载和使用:

    #!/usr/bin/env python
    
    import ConfigParser
    import io
    
    # Load the configuration file
    with open("config.yml") as f:
        sample_config = f.read()
    config = ConfigParser.RawConfigParser(allow_no_value=True)
    config.readfp(io.BytesIO(sample_config))
    
    # List all contents
    print("List all contents")
    for section in config.sections():
        print("Section: %s" % section)
        for options in config.options(section):
            print("x %s:::%s:::%s" % (options,
                                      config.get(section, options),
                                      str(type(options))))
    
    # Print some contents
    print("\nPrint some contents")
    print(config.get('other', 'use_anonymous'))  # Just get the value
    print(config.getboolean('other', 'use_anonymous'))  # You know the datatype?
    

    哪个输出

    List all contents
    Section: mysql
    x host:::localhost:::<type 'str'>
    x user:::root:::<type 'str'>
    x passwd:::my secret password:::<type 'str'>
    x db:::write-math:::<type 'str'>
    Section: other
    x preprocessing_queue:::["preprocessing.scale_and_center",
    "preprocessing.dot_reduction",
    "preprocessing.connect_lines"]:::<type 'str'>
    x use_anonymous:::yes:::<type 'str'>
    
    Print some contents
    yes
    True
    

    如您所见,您可以使用易于读写的标准数据格式。 getboolean 和 getint 等方法允许您获取数据类型而不是简单的字符串。

    编写配置

    import os
    configfile_name = "config.yaml"
    
    # Check if there is already a configurtion file
    if not os.path.isfile(configfile_name):
        # Create the configuration file as it doesn't exist yet
        cfgfile = open(configfile_name, 'w')
    
        # Add content to the file
        Config = ConfigParser.ConfigParser()
        Config.add_section('mysql')
        Config.set('mysql', 'host', 'localhost')
        Config.set('mysql', 'user', 'root')
        Config.set('mysql', 'passwd', 'my secret password')
        Config.set('mysql', 'db', 'write-math')
        Config.add_section('other')
        Config.set('other',
                   'preprocessing_queue',
                   ['preprocessing.scale_and_center',
                    'preprocessing.dot_reduction',
                    'preprocessing.connect_lines'])
        Config.set('other', 'use_anonymous', True)
        Config.write(cfgfile)
        cfgfile.close()
    

    结果

    [mysql]
    host = localhost
    user = root
    passwd = my secret password
    db = write-math
    
    [other]
    preprocessing_queue = ['preprocessing.scale_and_center', 'preprocessing.dot_reduction', 'preprocessing.connect_lines']
    use_anonymous = True
    

    XML 基本示例

    似乎根本不被 Python 社区用于配置文件。但是,解析/编写 XML 很容易,并且使用 Python 有很多可能性。一个是 BeautifulSoup:

    from BeautifulSoup import BeautifulSoup
    
    with open("config.xml") as f:
        content = f.read()
    
    y = BeautifulSoup(content)
    print(y.mysql.host.contents[0])
    for tag in y.other.preprocessing_queue:
        print(tag)
    

    config.xml 可能看起来像这样

    <config>
        <mysql>
            <host>localhost</host>
            <user>root</user>
            <passwd>my secret password</passwd>
            <db>write-math</db>
        </mysql>
        <other>
            <preprocessing_queue>
                <li>preprocessing.scale_and_center</li>
                <li>preprocessing.dot_reduction</li>
                <li>preprocessing.connect_lines</li>
            </preprocessing_queue>
            <use_anonymous value="true" />
        </other>
    </config>
    

    【讨论】:

    • 不错的代码/示例。小评论——您的 YAML 示例未使用 YAML,而是使用 INI 样式格式。
    • 需要注意的是,至少python 2版本的ConfigParser会在读取时静默地将存储的列表转换为字符串。 IE。 CP.set('section','option',[1,2,3]) 保存和读取配置后将是 CP.get('section','option') => '1, 2, 3'跨度>
    【解决方案5】:

    尝试使用ReadSettings

    from readsettings import ReadSettings
    data = ReadSettings("settings.json") # Load or create any json, yml, yaml or toml file
    data["name"] = "value" # Set "name" to "value"
    data["name"] # Returns: "value"
    

    【讨论】:

      【解决方案6】:

      尝试使用cfg4py:

      1. 分层设计,支持多种环境,因此切勿将开发设置与生产站点设置混为一谈。
      2. 代码完成。 Cfg4py 会将您的 yaml 转换为 python 类,然后在您输入代码时可以使用代码完成。
      3. 还有更多..

      免责声明:我是这个模块的作者

      【讨论】:

        【解决方案7】:

        对于简单的配置文件,我更喜欢 JSON 文件,例如conf.json

        {
          "version": 1,
          "bind": {
            "address": "127.0.0.1",
            "port": 8080
          },
          "data": {
            "a": [1, 2, 3],
            "b": 2.5
          }
        }
        

        然后创建这个自定义 JSON 配置阅读器:

        import json
        
        
        class Dict(dict):
            """dot.notation access to dictionary attributes"""
            __getattr__ = dict.get
            __setattr__ = dict.__setitem__
            __delattr__ = dict.__delitem__
        
        
        class Configuration(object):
        
            @staticmethod
            def __load__(data):
                if type(data) is dict:
                    return Configuration.load_dict(data)
                else:
                    return data
        
            @staticmethod
            def load_dict(data: dict):
                result = Dict()
                for key, value in data.items():
                    result[key] = Configuration.__load__(value)
                return result
        
            @staticmethod
            def load_json(path: str):
                with open(path, "r") as f:
                    result = Configuration.__load__(json.loads(f.read()))
                return result
        

        最后,使用命令加载它:

        confjson = Configuration.load_json('conf.json')
        

        现在您可以使用点“。”访问您的配置。例如:

        print(conf.version)
        print(conf.bind.address)
        print(conf.bind.port)
        print(conf.data.a)
        print(conf.data.b)
        

        【讨论】:

          猜你喜欢
          • 2020-10-05
          • 1970-01-01
          • 2016-10-06
          • 1970-01-01
          • 2011-09-29
          • 2013-04-06
          • 1970-01-01
          • 1970-01-01
          • 2021-09-25
          相关资源
          最近更新 更多