Python: ¿Cómo guardarías un archivo de configuración / configuración simple?

100

No me importa si se trata de JSON, pickle, YAML, o lo que sea.

Todas las demás implementaciones que he visto no son compatibles con versiones posteriores, por lo que si tengo un archivo de configuración, agrego una nueva clave en el código y luego cargue ese archivo de configuración, simplemente fallará.

¿Existe alguna forma sencilla de hacer esto?

usuario1438098
fuente
1
Creo que usar el .iniformato similar al del configparsermódulo debería hacer lo que quieres.
Bakuriu
14
¿Alguna posibilidad de seleccionar mi respuesta como correcta?
Graeme Stuart

Respuestas:

187

Archivos de configuración en Python

Hay varias formas de hacer esto según el formato de archivo requerido.

ConfigParser [formato .ini]

Usaría el enfoque de configparser estándar a menos que haya razones de peso para usar un formato diferente.

Escribe un archivo así:

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

El formato del archivo es muy simple con secciones marcadas entre corchetes:

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

Los valores se pueden extraer del archivo de la siguiente manera:

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

Los datos JSON pueden ser muy complejos y tienen la ventaja de ser altamente portátiles.

Escribe datos en un archivo:

import json

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

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

Leer datos de un archivo:

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

En esta respuesta se proporciona un ejemplo básico de YAML . Se pueden encontrar más detalles en el sitio web de pyYAML .

Graeme Stuart
fuente
8
en Python 3 from configparser import ConfigParser config = ConfigParser()
user3148949
12

Ejemplo básico de ConfigParser

El archivo se puede cargar y utilizar así:

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

que salidas

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 puede ver, puede utilizar un formato de datos estándar que sea fácil de leer y escribir. Los métodos como getboolean y getint le permiten obtener el tipo de datos en lugar de una simple cadena.

Configuración de escritura

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

resultados en

[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

Ejemplo básico de XML

Parece que la comunidad de Python no lo usa en absoluto para archivos de configuración. Sin embargo, analizar / escribir XML es fácil y hay muchas posibilidades para hacerlo con Python. Uno es 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)

donde el config.xml podría verse así

<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
fuente
Buen código / ejemplos. Comentario menor: su ejemplo de YAML no usa YAML sino un formato de estilo INI.
Eric Kramer
Cabe señalar que al menos la versión python 2 de ConfigParser convertirá silenciosamente la lista almacenada en una cadena al leerla. Es decir. CP.set ('sección', 'opción', [1,2,3]) después de guardar y leer la configuración será CP.get ('sección', 'opción') => '1, 2, 3'
Gnudiff
10

Si desea usar algo como un archivo INI para mantener la configuración, considere usar configparser que carga pares clave-valor de un archivo de texto y puede escribir fácilmente en el archivo.

El archivo INI tiene el formato:

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

Guarde y cargue un diccionario. Tendrá claves arbitrarias, valores y un número arbitrario de pares de claves y valores.

dmitri
fuente
¿Puedo usar la refactorización con esto?
Lore
1

Intente 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
fuente
-2

intente usar cfg4py :

  1. Diseño jerárquico, compatible con múltiples entornos, por lo que nunca estropee la configuración de desarrollo con la configuración del sitio de producción.
  2. Finalización de código. Cfg4py convertirá su yaml en una clase de python, luego la finalización del código estará disponible mientras escribe su código.
  3. mucho mas..

DESCARGO DE RESPONSABILIDAD: Soy el autor de este módulo

Aaron
fuente