- dom 26 maio 2024
- utils
- Giliard Godoi
- #config, #toml, #yaml
Este artigo faz parte de uma série de três publicações que tratam de arquivos de configurações comuns em projetos desenvolvidos em Python.
Esses formatos são config.ini
, yaml
, e toml
.
Serão apresentados as características básicas desses formatos, e quais bibliotecas podem ser utilizadas para manipular os arquivos de cada uma dessas extensões.
O artigo está organizado sob o formatos de perguntas e respostas, com o correspondente exemplo de um código, para facilitar consultas futuras.
Config initialization (config.ini)
Os arquivos .ini
foram primeiramente projetados para o sistema Microsoft Windows.
Contudo, eles foram adotados por outros softwares (inclusives de código aberto) onde podem aparecer sob a extensão .cfg
com implementações ligeiramente diferente.
Basicamente, as informações são guardadas sob o esquema chave-valor e podem ser organizadas em diversas seções.
O arquivo no entando deve possuir uma sessão DEFAULT
.
A manipulação desses arquivos podem ser feitas pela biblioteca padrão configparser
.
As principais características desse formato são:
- Ser facilmente lido (e entendido) por um humano
- Podem ser utilizados como delimitadores de valor os caracteres ‘
=
‘ ou ‘:
‘. - Comentários são precedidos pelo caracter ‘
#
‘ - Todos os valores são convertidos para
string
, porém existem alguns métodos especiais para converter os valores para determinado tipo; - Ao realizar o parse de um arquivo, a estrutura de dados retornados se assemelha a um dicionário do Python.
O básico sobre configparser
Um exemplo da organização desse arquivo pode ser vista em configuration_string
, conforme definido abaixo:
import configparser
config = configparser.ConfigParser()
configuration_string = '''
[DEFAULT]
name = Giliard Godoi
email = ggodoi@email.com
local = Brasil
secret_agent = True
# This is a comment
[education]
school = Federal University of Technology - Paraná
major = Software Development
year = 2018
# This is a list of skills
[skills]
programing :
Python
JavaScript
C
C++
language :
Portuguese
English
'''
Como realizar o parse da string?
config.read_string(configuration_string)
type(
config
)
configparser.ConfigParser
def __init__(defaults=None, dict_type=_default_dict, allow_no_value=False, *, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=DEFAULTSECT, interpolation=_UNSET, converters=_UNSET)
ConfigParser implementing interpolation.
O que é uma seção?
config['DEFAULT']
<Section: DEFAULT>
Como saber quais são as demais seções?
config.sections()
['education', 'skills']
Como verificar se uma seção existe dentro de um objeto config
?
('education' in config) or config.has_section('education')
True
Como verificar se existe uma opção (chave) dentro de uma seção?
config.has_option(section='education', option='year')
True
Como verificar se existe uma opção para a seção default?
'''
Se especificado `section` igual a None ou string vazia, a seção default é verificada.
'''
config.has_option(section=None, option='company')
False
config.has_option(section=None, option='email')
True
Como acessar um valor na seção default?
config['DEFAULT']['name']
'Giliard Godoi'
Como acessar um valor em uma outra seção?
config['education']['school']
'Federal University of Technology - Paraná'
Ou então, utilizar o método get
config.get(section='education', option='school')
'Federal University of Technology - Paraná'
Qual é o tipo de dado retornado por padrão?
type(
config['education']['year']
)
str
Isso serve também para listas?
config['skills']['programing']
'\nPython\nJavaScript\nC\nC++'
Como converter os valores para listas?
config['skills']['programing'].split()
['Python', 'JavaScript', 'C', 'C++']
No entanto, a conversão (parse) para listas não é nativamente implementada para a linguagem Python.
Como converter o valor de uma variável para um tipo específico?
print(f'''
-----------------------------------
{config.get(section='education', option='school')} : {type(config.get(section='education', option='school'))}
{config.getint('education', 'year')} : {type(config.getint('education', 'year'))}
{config.getboolean('DEFAULT', 'secret_agent')} : {type(config.getboolean('DEFAULT', 'secret_agent'))}
-----------------------------------
''')
-----------------------------------
Federal University of Technology - Paraná : <class 'str'>
2018 : <class 'int'>
True : <class 'bool'>
-----------------------------------
Ou seja, existem três métodos para converter para tipos específicos:
getint
getfloat
getboolean
type(
config.getint('education', 'year')
)
int
type(
config.getboolean('DEFAULT', 'secret_agent')
)
bool
É possível definir um valor fallback nos métodos get?
assert not config.has_option(section='company', option='name')
config.get(section='company', option='name', fallback='Does not exist')
'Does not exist'
Como saber todas as variáveis existentes de uma seção?
config.options('education')
['school', 'major', 'year', 'name', 'email', 'local', 'secret_agent']
Como obter os itens (chave-valor) para uma seção?
config.items('education')
[('name', 'Giliard Godoi'),
('email', 'ggodoi@email.com'),
('local', 'Brasil'),
('secret_agent', 'True'),
('school', 'Federal University of Technology - Paraná'),
('major', 'Software Development'),
('year', '2018')]
Como obter os itens (chave-valor) para a seção default?
config.defaults()
{
'name': 'Giliard Godoi',
'email': 'ggodoi@email.com',
'local': 'Brasil',
'secret_agent': 'True'
}
Arquivos
As operações de leitura e escrita do arquivo são bem simples, como pode ser visto a seguir.
Como salvar as configurações em um arquivo?
with open('config.ini', 'w') as f:
config.write(f)
Como ler o arquivo config.ini?
other = configparser.ConfigParser()
other.sections()
[]
other.read('config.ini')
['config.ini']
other.sections()
['education', 'skills']