144

我不在乎它是JSON, pickle,YAML还是什么的。

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

有什么简单的方法可以做到这一点吗?

4

7 回答 7

240

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

此答案中提供了一个基本的 YAML 示例。更多细节可以在pyYAML 网站上找到。

于 2013-09-29T13:42:09.717 回答
13

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>
于 2015-01-11T19:41:41.123 回答
11

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

INI 文件的格式为:

[Section]
key = value
key with spaces = somevalue
于 2013-09-29T12:52:15.067 回答
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)
于 2021-07-04T10:58:08.960 回答
2

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

于 2013-09-29T12:48:14.857 回答
0

尝试使用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"
于 2019-04-08T10:07:56.923 回答
-2

尝试使用cfg4py

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

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

于 2020-05-02T12:14:25.740 回答