Python: Como você salvaria um arquivo simples de configurações / configurações?

101

Eu não me importo se é JSON, pickle, YAML, ou o que quer.

Todas as outras implementações que vi não são compatíveis com versões futuras, portanto, se eu tiver um arquivo de configuração, adicionar uma nova chave no código e carregar esse arquivo de configuração, ele simplesmente travará.

Existe alguma maneira simples de fazer isso?

user1438098
fonte
1
Acredito que usar o .iniformato -like do configparsermódulo deve fazer o que você quiser.
Bakuriu
14
alguma chance de selecionar minha resposta como correta?
Graeme Stuart

Respostas:

187

Arquivos de configuração em python

Existem várias maneiras de fazer isso, dependendo do formato de arquivo necessário.

ConfigParser [formato .ini]

Eu usaria a abordagem do configparser padrão , a menos que houvesse motivos convincentes para usar um formato diferente.

Escreva um arquivo como este:

# 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)

O formato do arquivo é muito simples, com seções marcadas entre colchetes:

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

Os valores podem ser extraídos do arquivo como:

# 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 [formato .json]

Os dados JSON podem ser muito complexos e têm a vantagem de serem altamente portáteis.

Grave dados em um arquivo:

import json

config = {'key1': 'value1', 'key2': 'value2'}

with open('config.json', 'w') as f:
    json.dump(config, f)

Leia os dados de um arquivo:

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

Um exemplo básico de YAML é fornecido nesta resposta . Mais detalhes podem ser encontrados no site da pyYAML .

Graeme Stuart
fonte
8
em python 3 from configparser import ConfigParser config = ConfigParser()
user3148949
12

Exemplo básico do ConfigParser

O arquivo pode ser carregado e usado assim:

#!/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?

quais saídas

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

Como você pode ver, você pode usar um formato de dados padrão fácil de ler e gravar. Métodos como getboolean e getint permitem que você obtenha o tipo de dados em vez de uma string simples.

Configuração de gravação

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()

resulta em

[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

Exemplo básico de XML

Parece não ser usado para arquivos de configuração pela comunidade Python. No entanto, analisar / escrever XML é fácil e há muitas possibilidades de fazer isso com Python. Um é 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)

onde o config.xml pode se parecer com este

<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>
scre_www
fonte
Bom código / exemplos. Comentário secundário - seu exemplo YAML não está usando YAML, mas o formato no estilo INI.
Eric Kramer
Deve-se observar que pelo menos a versão python 2 do ConfigParser converterá silenciosamente a lista armazenada em string durante a leitura. Ou seja, CP.set ('seção', 'opção', [1,2,3]) após salvar e ler a configuração será CP.get ('seção', 'opção') => '1, 2, 3'
Gnudiff
10

Se você quiser usar algo como um arquivo INI para manter as configurações, considere usar o configparser, que carrega pares de valores-chave de um arquivo de texto e pode facilmente gravar de volta no arquivo.

O arquivo INI tem o formato:

[Section]
key = value
key with spaces = somevalue
Tadgh
fonte
2

Salve e carregue um dicionário. Você terá chaves, valores e número arbitrário de pares de chaves e valores arbitrários.

Dimitri
fonte
posso usar refatoração com isso?
Lore
1

Tente usar 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"
Richie Bendall
fonte
-2

tente usar cfg4py :

  1. Design hierárquico, com suporte para múltiplos envios, então nunca bagunce as configurações de desenvolvimento com as configurações do site de produção.
  2. Preenchimento de código. Cfg4py irá converter seu yaml em uma classe python, então o auto-completar de código estará disponível enquanto você digita seu código.
  3. muito mais..

AVISO LEGAL: Eu sou o autor deste módulo

Aaron
fonte