configparser — Trabajar con archivos de configuración

Propósito:Leer/escribir archivos de configuración similares a los archivos INI de Windows

Usa el módulo configparser para gestionar archivos de configuración editables por el usuario para una aplicación. El contenido de los archivos de configuración se puede organizar en grupos y se admiten varios tipos de valores de opción, incluidos enteros, valores de coma flotante y booleanos. Los valores de las opciones se pueden combinar utilizando cadenas de formateo de Python, para crear valores más largos, como URLs de valores más cortos, como nombres de host y números de puerto.

Formato de archivo de configuración

El formato de archivo utilizado por configparser es similar al formato utilizado por versiones anteriores de Microsoft Windows. Consiste en una o secciones más nombradas, cada una de las cuales puede contener opciones individuales con nombres y valores.

Las secciones del archivo de configuración se identifican buscando líneas que comiencen con [ y terminen con ]. El valor entre corchetes es el nombre de la sección, y puede contener cualquier carácter excepto los corchetes.

Las opciones se enumeran una por línea dentro de una sección. La linea comienza con el nombre de la opción, que está separada del valor por dos puntos (:) o un signo igual (=). Espacio en blanco alrededor del separador se ignoran cuando se analiza el archivo.

Las líneas que comienzan con punto y coma (;) o numeral (#) son tratadas como comentarios y no visibles al acceder a los contenidos del archivo de configuración mediante programación.

Este archivo de configuración de muestra tiene una sección llamada bug_tracker con tres opciones, url, username y password.

# This is a simple example with comments.
[bug_tracker]
url = http://localhost:8080/bugs/
username = dhellmann
; You should not store passwords in plain text
; configuration files.
password = SECRET

Lectura de archivos de configuración

El uso más común para un archivo de configuración es hacer que un usuario o administrador del sistema edite el archivo con un editor de texto normal para establecer los valores predeterminados de comportamiento de la aplicación y luego hacer que la aplicación lea el archivo, lo analice y actúe en función de su contenido. Usa el método read() de ConfigParser para leer el archivo de configuración.

configparser_read.py
from configparser import ConfigParser

parser = ConfigParser()
parser.read('simple.ini')

print(parser.get('bug_tracker', 'url'))

Este programa lee el archivo simple.ini de la sección anterior e imprime el valor de la opción url de la sección bug_tracker.

$ python3 configparser_read.py

http://localhost:8080/bugs/

El método read() también acepta una lista de nombres de archivo. A su vez, se escanea cada nombre y, si el archivo existe, se abre y se lee.

configparser_read_many.py
from configparser import ConfigParser
import glob

parser = ConfigParser()

candidates = ['does_not_exist.ini', 'also-does-not-exist.ini',
              'simple.ini', 'multisection.ini']

found = parser.read(candidates)

missing = set(candidates) - set(found)

print('Found config files:', sorted(found))
print('Missing files     :', sorted(missing))

read() devuelve una lista que contiene los nombres de los archivos cargados con éxito, para que el programa pueda descubrir qué archivos de configuración faltan y decidir si los ignora o trata la condición como un error.

$ python3 configparser_read_many.py

Found config files: ['multisection.ini', 'simple.ini']
Missing files     : ['also-does-not-exist.ini',
'does_not_exist.ini']

Datos de configuración Unicode

Los archivos de configuración que contienen datos Unicode deben leerse utilizando el valor de codificación adecuado. El siguiente archivo de ejemplo cambia el valor de la contraseña de la entrada original para contener caracteres Unicode y se codifica con UTF-8.

unicode.ini
[bug_tracker]
url = http://localhost:8080/bugs/
username = dhellmann
password = ßéç®é†

El archivo se abre con el decodificador apropiado, convirtiendo los datos UTF-8 en cadenas Unicode nativas.

configparser_unicode.py
from configparser import ConfigParser
import codecs

parser = ConfigParser()
# Open the file with the correct encoding
parser.read('unicode.ini', encoding='utf-8')

password = parser.get('bug_tracker', 'password')

print('Password:', password.encode('utf-8'))
print('Type    :', type(password))
print('repr()  :', repr(password))

El valor devuelto por get() es una cadena Unicode, por lo que para imprimirla de manera segura debe volver a codificarse como UTF-8.

$ python3 configparser_unicode.py

Password: b'\xc3\x9f\xc3\xa9\xc3\xa7\xc2\xae\xc3\xa9\xe2\x80\xa0
'
Type    : <class 'str'>
repr()  : 'ßéç®é†'

Acceso a los ajustes de configuración

ConfigParser incluye métodos para examinar la estructura de la configuración analizada, incluida la lista de secciones y opciones, y obtener sus valores. Este archivo de configuración incluye dos secciones para servicios web separados.

[bug_tracker]
url = http://localhost:8080/bugs/
username = dhellmann
password = SECRET

[wiki]
url = http://localhost:8080/wiki/
username = dhellmann
password = SECRET

Y este programa de ejemplo ejercita algunos de los métodos para observar los datos de configuración, incluyendo las sections(), options() e items().

configparser_structure.py
from configparser import ConfigParser

parser = ConfigParser()
parser.read('multisection.ini')

for section_name in parser.sections():
    print('Section:', section_name)
    print('  Options:', parser.options(section_name))
    for name, value in parser.items(section_name):
        print('  {} = {}'.format(name, value))
    print()

Ambos sections y options devuelven listas de cadenas, mientras que items() devuelve una lista de tuplas que contienen los pares nombre-valor.

$ python3 configparser_structure.py

Section: bug_tracker
  Options: ['url', 'username', 'password']
  url = http://localhost:8080/bugs/
  username = dhellmann
  password = SECRET

Section: wiki
  Options: ['url', 'username', 'password']
  url = http://localhost:8080/wiki/
  username = dhellmann
  password = SECRET

Un ConfigParser también admite la misma interfaz de programación de mapeo que dict, con el ConfigParser actuando como un diccionario que contiene diccionarios separados para cada sección.

configparser_structure_dict.py
from configparser import ConfigParser

parser = ConfigParser()
parser.read('multisection.ini')

for section_name in parser:
    print('Section:', section_name)
    section = parser[section_name]
    print('  Options:', list(section.keys()))
    for name in section:
        print('  {} = {}'.format(name, section[name]))
    print()

El uso de la interfaz de programación de mapeo para acceder al mismo archivo de configuración produce el mismo resultado.

$ python3 configparser_structure_dict.py

Section: DEFAULT
  Options: []

Section: bug_tracker
  Options: ['url', 'username', 'password']
  url = http://localhost:8080/bugs/
  username = dhellmann
  password = SECRET

Section: wiki
  Options: ['url', 'username', 'password']
  url = http://localhost:8080/wiki/
  username = dhellmann
  password = SECRET

Prueba si los valores están presentes

Para probar si existe una sección, usa has_section(), pasando el nombre de la sección.

configparser_has_section.py
from configparser import ConfigParser

parser = ConfigParser()
parser.read('multisection.ini')

for candidate in ['wiki', 'bug_tracker', 'dvcs']:
    print('{:<12}: {}'.format(
        candidate, parser.has_section(candidate)))

Probar si existe una sección antes de llamar a get() evita excepciones en datos faltantes.

$ python3 configparser_has_section.py

wiki        : True
bug_tracker : True
dvcs        : False

Usa has_option() para probar si existe una opción dentro de una sección.

configparser_has_option.py
from configparser import ConfigParser

parser = ConfigParser()
parser.read('multisection.ini')

SECTIONS = ['wiki', 'none']
OPTIONS = ['username', 'password', 'url', 'description']

for section in SECTIONS:
    has_section = parser.has_section(section)
    print('{} section exists: {}'.format(section, has_section))
    for candidate in OPTIONS:
        has_option = parser.has_option(section, candidate)
        print('{}.{:<12}  : {}'.format(
            section, candidate, has_option))
    print()

Si la sección no existe, has_option() devuelve False.

$ python3 configparser_has_option.py

wiki section exists: True
wiki.username      : True
wiki.password      : True
wiki.url           : True
wiki.description   : False

none section exists: False
none.username      : False
none.password      : False
none.url           : False
none.description   : False

Tipos de valor

Todos los nombres de secciones y opciones se tratan como cadenas, pero los valores de las opciones pueden ser cadenas, enteros, números de coma flotante o booleanos. Hay un rango de posibles valores booleanos que se convierten en verdadero o falso. El siguiente archivo de ejemplo incluye uno de cada uno.

types.ini
[ints]
positive = 1
negative = -5

[floats]
positive = 0.2
negative = -3.14

[booleans]
number_true = 1
number_false = 0
yn_true = yes
yn_false = no
tf_true = true
tf_false = false
onoff_true = on
onoff_false = false

ConfigParser no intenta comprender el tipo de opción. Se espera que la aplicación use el método correcto para obtener el valor como el tipo deseado. get() siempre devuelve una cadena. Usa getint() para enteros, getfloat() para números de coma flotante y getboolean() para valores booleanos.

configparser_value_types.py
from configparser import ConfigParser

parser = ConfigParser()
parser.read('types.ini')

print('Integers:')
for name in parser.options('ints'):
    string_value = parser.get('ints', name)
    value = parser.getint('ints', name)
    print('  {:<12} : {!r:<7} -> {}'.format(
        name, string_value, value))

print('\nFloats:')
for name in parser.options('floats'):
    string_value = parser.get('floats', name)
    value = parser.getfloat('floats', name)
    print('  {:<12} : {!r:<7} -> {:0.2f}'.format(
        name, string_value, value))

print('\nBooleans:')
for name in parser.options('booleans'):
    string_value = parser.get('booleans', name)
    value = parser.getboolean('booleans', name)
    print('  {:<12} : {!r:<7} -> {}'.format(
        name, string_value, value))

Ejecutar este programa con la entrada de ejemplo produce la siguiente salida.

$ python3 configparser_value_types.py

Integers:
  positive     : '1'     -> 1
  negative     : '-5'    -> -5

Floats:
  positive     : '0.2'   -> 0.20
  negative     : '-3.14' -> -3.14

Booleans:
  number_true  : '1'     -> True
  number_false : '0'     -> False
  yn_true      : 'yes'   -> True
  yn_false     : 'no'    -> False
  tf_true      : 'true'  -> True
  tf_false     : 'false' -> False
  onoff_true   : 'on'    -> True
  onoff_false  : 'false' -> False

Convertidores de tipo personalizado se pueden agregar pasando funciones de conversión en el argumento converters de ConfigParser. Cada convertidor recibe un único valor de entrada y debe transformar ese valor en el tipo de retorno apropiado.

configparser_custom_types.py
from configparser import ConfigParser
import datetime


def parse_iso_datetime(s):
    print('parse_iso_datetime({!r})'.format(s))
    return datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')


parser = ConfigParser(
    converters={
        'datetime': parse_iso_datetime,
    }
)
parser.read('custom_types.ini')

string_value = parser['datetimes']['due_date']
value = parser.getdatetime('datetimes', 'due_date')
print('due_date : {!r} -> {!r}'.format(string_value, value))

Agregar un convertidor hace que ConfigParser cree automáticamente un método de recuperación para ese tipo, utilizando el nombre del tipo especificado en converters. En este ejemplo, el convertidor 'datetime' hace que se agregue un nuevo método getdatetime().

$ python3 configparser_custom_types.py

parse_iso_datetime('2015-11-08T11:30:05.905898')
due_date : '2015-11-08T11:30:05.905898' -> datetime.datetime(201
5, 11, 8, 11, 30, 5, 905898)

También es posible agregar métodos de conversión directamente a una subclase de ConfigParser.

Opciones como banderas

Por lo general, el analizador requiere un valor explícito para cada opción, pero con el parámetro allow_no_value de ConfigParser establecido en True, una opción puede aparecer por sí misma en una línea en el archivo de entrada y puede usarse como una bandera.

configparser_allow_no_value.py
import configparser

# Require values
try:
    parser = configparser.ConfigParser()
    parser.read('allow_no_value.ini')
except configparser.ParsingError as err:
    print('Could not parse:', err)

# Allow stand-alone option names
print('\nTrying again with allow_no_value=True')
parser = configparser.ConfigParser(allow_no_value=True)
parser.read('allow_no_value.ini')
for flag in ['turn_feature_on', 'turn_other_feature_on']:
    print('\n', flag)
    exists = parser.has_option('flags', flag)
    print('  has_option:', exists)
    if exists:
        print('         get:', parser.get('flags', flag))

Cuando una opción no tiene un valor explícito, has_option() informa que la opción existe y get() devuelve None.

$ python3 configparser_allow_no_value.py

Could not parse: Source contains parsing errors:
'allow_no_value.ini'
        [line  2]: 'turn_feature_on\n'

Trying again with allow_no_value=True

 turn_feature_on
  has_option: True
         get: None

 turn_other_feature_on
  has_option: False

Cadenas multilínea

Los valores de cadena pueden abarcar varias líneas, si las líneas posteriores están sangradas.

[example]
message = This is a multi-line string.
  With two paragraphs.

  They are separated by a completely empty line.

Dentro de los valores de varias líneas sangradas, las líneas en blanco se tratan como parte del valor y se conservan.

$ python3 configparser_multiline.py

This is a multi-line string.
With two paragraphs.

They are separated by a completely empty line.

Modificar configuraciones

Si bien ConfigParser está diseñado principalmente para leer la configuración desde archivos, la configuración también se puede completar llamando a add_section() para crear una nueva sección y set() para agregar o cambiar una opción.

configparser_populate.py
import configparser

parser = configparser.SafeConfigParser()

parser.add_section('bug_tracker')
parser.set('bug_tracker', 'url', 'http://localhost:8080/bugs')
parser.set('bug_tracker', 'username', 'dhellmann')
parser.set('bug_tracker', 'password', 'secret')

for section in parser.sections():
    print(section)
    for name, value in parser.items(section):
        print('  {} = {!r}'.format(name, value))

Todas las opciones deben establecerse como cadenas, incluso si se recuperarán como valores enteros, flotantes o booleanos.

$ python3 configparser_populate.py

bug_tracker
  url = 'http://localhost:8080/bugs'
  username = 'dhellmann'
  password = 'secret'

Las secciones y opciones se pueden eliminar de un ConfigParser con remove_section() y remove_option().

configparser_remove.py
from configparser import ConfigParser

parser = ConfigParser()
parser.read('multisection.ini')

print('Read values:\n')
for section in parser.sections():
    print(section)
    for name, value in parser.items(section):
        print('  {} = {!r}'.format(name, value))

parser.remove_option('bug_tracker', 'password')
parser.remove_section('wiki')

print('\nModified values:\n')
for section in parser.sections():
    print(section)
    for name, value in parser.items(section):
        print('  {} = {!r}'.format(name, value))

Al eliminar una sección, se eliminan las opciones que contiene.

$ python3 configparser_remove.py

Read values:

bug_tracker
  url = 'http://localhost:8080/bugs/'
  username = 'dhellmann'
  password = 'SECRET'
wiki
  url = 'http://localhost:8080/wiki/'
  username = 'dhellmann'
  password = 'SECRET'

Modified values:

bug_tracker
  url = 'http://localhost:8080/bugs/'
  username = 'dhellmann'

Guardar archivos de configuración

Una vez que un ConfigParser se llena con los datos deseados, se puede guardar en un archivo llamando al método write(). Esto hace posible proporcionar una interfaz de usuario para editar las configuraciones, sin tener que escribir ningún código para gestionar el archivo.

configparser_write.py
import configparser
import sys

parser = configparser.ConfigParser()

parser.add_section('bug_tracker')
parser.set('bug_tracker', 'url', 'http://localhost:8080/bugs')
parser.set('bug_tracker', 'username', 'dhellmann')
parser.set('bug_tracker', 'password', 'secret')

parser.write(sys.stdout)

El método write() toma un objeto similar a un archivo como argumento. Escribe los datos en el formato INI para que pueda ser analizado nuevamente por ConfigParser.

$ python3 configparser_write.py

[bug_tracker]
url = http://localhost:8080/bugs
username = dhellmann
password = secret

Advertencia

Los comentarios en el archivo de configuración original no se conservan al leer, modificar y reescribir un archivo de configuración.

Opción ruta de búsqueda

ConfigParser utiliza un proceso de búsqueda de varios pasos cuando busca una opción.

Antes de comenzar la búsqueda de opciones, se prueba el nombre de la sección. Si la sección no existe, y el nombre no es el valor especial DEFAULT, entonces se plantea la excepción NoSectionError.

  1. Si el nombre de la opción aparece en el diccionario vars pasado a get(), se devuelve el valor de vars.
  2. Si el nombre de la opción aparece en la sección especificada, se devuelve el valor de esa sección.
  3. Si el nombre de la opción aparece en la sección DEFAULT, se devuelve ese valor.
  4. Si el nombre de la opción aparece en el diccionario de defaults pasado al constructor, se devuelve ese valor.

Si el nombre no se encuentra en ninguna de esas ubicaciones, se plantea la excepción NoOptionError

El comportamiento de la ruta de búsqueda se puede demostrar con este archivo de configuración.

[DEFAULT]
file-only = value from DEFAULT section
init-and-file = value from DEFAULT section
from-section = value from DEFAULT section
from-vars = value from DEFAULT section

[sect]
section-only = value from section in file
from-section = value from section in file
from-vars = value from section in file

Este programa de prueba incluye configuraciones predeterminadas para las opciones no especificadas en el archivo de configuración y anula algunos valores definidos en el archivo.

configparser_defaults.py
import configparser

# Define the names of the options
option_names = [
    'from-default',
    'from-section', 'section-only',
    'file-only', 'init-only', 'init-and-file',
    'from-vars',
]

# Initialize the parser with some defaults
DEFAULTS = {
    'from-default': 'value from defaults passed to init',
    'init-only': 'value from defaults passed to init',
    'init-and-file': 'value from defaults passed to init',
    'from-section': 'value from defaults passed to init',
    'from-vars': 'value from defaults passed to init',
}
parser = configparser.ConfigParser(defaults=DEFAULTS)

print('Defaults before loading file:')
defaults = parser.defaults()
for name in option_names:
    if name in defaults:
        print('  {:<15} = {!r}'.format(name, defaults[name]))

# Load the configuration file
parser.read('with-defaults.ini')

print('\nDefaults after loading file:')
defaults = parser.defaults()
for name in option_names:
    if name in defaults:
        print('  {:<15} = {!r}'.format(name, defaults[name]))

# Define some local overrides
vars = {'from-vars': 'value from vars'}

# Show the values of all the options
print('\nOption lookup:')
for name in option_names:
    value = parser.get('sect', name, vars=vars)
    print('  {:<15} = {!r}'.format(name, value))

# Show error messages for options that do not exist
print('\nError cases:')
try:
    print('No such option :', parser.get('sect', 'no-option'))
except configparser.NoOptionError as err:
    print(err)

try:
    print('No such section:', parser.get('no-sect', 'no-option'))
except configparser.NoSectionError as err:
    print(err)

El resultado muestra el origen del valor de cada opción e ilustra la forma en que los valores predeterminados de diferentes fuentes anulan los valores existentes.

$ python3 configparser_defaults.py

Defaults before loading file:
  from-default    = 'value from defaults passed to init'
  from-section    = 'value from defaults passed to init'
  init-only       = 'value from defaults passed to init'
  init-and-file   = 'value from defaults passed to init'
  from-vars       = 'value from defaults passed to init'

Defaults after loading file:
  from-default    = 'value from defaults passed to init'
  from-section    = 'value from DEFAULT section'
  file-only       = 'value from DEFAULT section'
  init-only       = 'value from defaults passed to init'
  init-and-file   = 'value from DEFAULT section'
  from-vars       = 'value from DEFAULT section'

Option lookup:
  from-default    = 'value from defaults passed to init'
  from-section    = 'value from section in file'
  section-only    = 'value from section in file'
  file-only       = 'value from DEFAULT section'
  init-only       = 'value from defaults passed to init'
  init-and-file   = 'value from DEFAULT section'
  from-vars       = 'value from vars'

Error cases:
No option 'no-option' in section: 'sect'
No section: 'no-sect'

Combinar valores con interpolación

ConfigParser proporciona una función llamada interpolación que se puede usar para combinar valores juntos. Los valores que contienen cadenas de formato Python estándar activan la función de interpolación cuando se recuperan. Las opciones nombradas dentro del valor que se está recuperando se reemplazan por sus valores, hasta que no sea necesaria más sustitución.

Los ejemplos de URL de esta sección pueden reescribirse para usar la interpolación para facilitar el cambio de solo una parte del valor. Por ejemplo, este archivo de configuración separa el protocolo, el nombre de host y el puerto de la URL como opciones separadas.

[bug_tracker]
protocol = http
server = localhost
port = 8080
url = %(protocol)s://%(server)s:%(port)s/bugs/
username = dhellmann
password = SECRET

La interpolación se realiza por defecto cada vez que se llama a get(). Pasa un valor verdadero en el argumento raw para recuperar el valor original, sin interpolación.

configparser_interpolation.py
from configparser import ConfigParser

parser = ConfigParser()
parser.read('interpolation.ini')

print('Original value       :', parser.get('bug_tracker', 'url'))

parser.set('bug_tracker', 'port', '9090')
print('Altered port value   :', parser.get('bug_tracker', 'url'))

print('Without interpolation:', parser.get('bug_tracker', 'url',
                                           raw=True))

Debido a que el valor se calcula mediante get(), al cambiar una de las configuraciones utilizadas por el valor url, se cambia el valor de retorno.

$ python3 configparser_interpolation.py

Original value       : http://localhost:8080/bugs/
Altered port value   : http://localhost:9090/bugs/
Without interpolation: %(protocol)s://%(server)s:%(port)s/bugs/

Usar valores predeterminados

Los valores para la interpolación no necesitan aparecer en la misma sección que la opción original. Los valores predeterminados se pueden mezclar con valores de anulación.

[DEFAULT]
url = %(protocol)s://%(server)s:%(port)s/bugs/
protocol = http
server = bugs.example.com
port = 80

[bug_tracker]
server = localhost
port = 8080
username = dhellmann
password = SECRET

Con esta configuración, el valor para url proviene de la sección DEFAULT, y la sustitución comienza buscando en bug_tracker y volviendo a DEFAULT para las partes no encontradas.

configparser_interpolation_defaults.py
from configparser import ConfigParser

parser = ConfigParser()
parser.read('interpolation_defaults.ini')

print('URL:', parser.get('bug_tracker', 'url'))

Los valores hostname y port provienen de la sección bug_tracker, pero el protocol proviene de DEFAULT.

$ python3 configparser_interpolation_defaults.py

URL: http://localhost:8080/bugs/

Errores de sustitución

La sustitución se detiene después de MAX_INTERPOLATION_DEPTH pasos para evitar problemas debido a referencias recursivas.

configparser_interpolation_recursion.py
import configparser

parser = configparser.ConfigParser()

parser.add_section('sect')
parser.set('sect', 'opt', '%(opt)s')

try:
    print(parser.get('sect', 'opt'))
except configparser.InterpolationDepthError as err:
    print('ERROR:', err)

Se plantea una excepción InterpolationDepthError si hay demasiados pasos de sustitución.

$ python3 configparser_interpolation_recursion.py

ERROR: Recursion limit exceeded in value substitution: option 'o
pt' in section 'sect' contains an interpolation key which cannot
 be substituted in 10 steps. Raw value: '%(opt)s'

Los valores faltantes dan como resultado una excepción InterpolationMissingOptionError.

configparser_interpolation_error.py
import configparser

parser = configparser.ConfigParser()

parser.add_section('bug_tracker')
parser.set('bug_tracker', 'url',
           'http://%(server)s:%(port)s/bugs')

try:
    print(parser.get('bug_tracker', 'url'))
except configparser.InterpolationMissingOptionError as err:
    print('ERROR:', err)

Como no se define ningún valor de server, no se puede construir la url.

$ python3 configparser_interpolation_error.py

ERROR: Bad value substitution: option 'url' in section
'bug_tracker' contains an interpolation key 'server' which is
not a valid option name. Raw value:
'http://%(server)s:%(port)s/bugs'

Escapar caracteres especiales

Dado que % inicia las instrucciones de interpolación, un literal % en un valor debe escaparse como %%.

[escape]
value = a literal %% must be escaped

Leer el valor no requiere ninguna consideración especial.

configparser_escape.py
from configparser import ConfigParser
import os

filename = 'escape.ini'
config = ConfigParser()
config.read([filename])

value = config.get('escape', 'value')

print(value)

Cuando se lee el valor, el %% se convierte a % automáticamente.

$ python3 configparser_escape.py

a literal % must be escaped

Interpolación extendida

ConfigParser admite implementaciones alternativas de interpolación pasando un objeto que admita la interfaz de programación definida por Interpolation al parámetro interpolation. Por ejemplo, usar ExtendedInterpolation en lugar del predeterminado BasicInterpolation habilita una sintaxis diferente usando ${} para indicar variables.

configparser_extendedinterpolation.py
from configparser import ConfigParser, ExtendedInterpolation

parser = ConfigParser(interpolation=ExtendedInterpolation())
parser.read('extended_interpolation.ini')

print('Original value       :', parser.get('bug_tracker', 'url'))

parser.set('intranet', 'port', '9090')
print('Altered port value   :', parser.get('bug_tracker', 'url'))

print('Without interpolation:', parser.get('bug_tracker', 'url',
                                           raw=True))

La interpolación extendida admite el acceso a valores de otras secciones del archivo de configuración al prefijar el nombre de la variable con el nombre de la sección y dos puntos (:).

[intranet]
server = localhost
port = 8080

[bug_tracker]
url = http://${intranet:server}:${intranet:port}/bugs/
username = dhellmann
password = SECRET

Hacer referencia a los valores en otras secciones del archivo permite compartir una jerarquía de valores, sin colocar todos los valores predeterminados en la sección DEFAULTS.

$ python3 configparser_extendedinterpolation.py

Original value       : http://localhost:8080/bugs/
Altered port value   : http://localhost:9090/bugs/
Without interpolation: http://${intranet:server}:${intranet:port
}/bugs/

Deshabilitar la interpolación

Para deshabilitar la interpolación, pasa None en lugar de un objeto Interpolation.

configparser_nointerpolation.py
from configparser import ConfigParser

parser = ConfigParser(interpolation=None)
parser.read('interpolation.ini')

print('Without interpolation:', parser.get('bug_tracker', 'url'))

Esto permite que cualquier sintaxis que pueda haber sido procesada por el objeto de interpolación sea ignorada de manera segura.

$ python3 configparser_nointerpolation.py

Without interpolation: %(protocol)s://%(server)s:%(port)s/bugs/

Ver también