A principal questão é: você deseja que seu arquivo de configuração esteja em uma linguagem completa de Turing (como é o Python)? Se você quiser isso, considere também incorporar alguma outra linguagem de script (completa de Turing) como Guile ou Lua (porque pode ser percebido como "mais simples" de usar ou incorporar do que o Python; leia o capítulo em Estendendo e Incorporando Python ). Não discutirei mais isso (porque outras respostas - por Amon - discutiram isso em profundidade), mas observe que a incorporação de uma linguagem de script em seu aplicativo é uma das principais opções de arquitetura , que você deve considerar muito cedo; Eu realmente não recomendo fazer essa escolha mais tarde!
Um exemplo bem conhecido de um programa configurável através de "scripts" é o editor GNU emacs (ou provavelmente o AutoCAD na região proprietária); lembre-se de que, se você aceitar scripts, algum usuário poderá eventualmente usar - e talvez abusar, no seu ponto de vista - esse recurso extensivamente e criar um script com milhares de linhas; portanto, a escolha de uma linguagem de script suficientemente boa é importante.
No entanto (pelo menos nos sistemas POSIX), você pode considerar conveniente permitir que o "arquivo" de configuração seja computado dinamicamente no momento da inicialização (é claro, deixando a carga de uma configuração sã para o administrador ou usuário do sistema; na verdade, é uma configuração texto que vem de algum arquivo ou de algum comando). Para isso, você pode simplesmente adotar a convenção (e documentá- la) de que um caminho de arquivo de configuração começando com, por exemplo, a !
ou a |
é na verdade um comando shell que você leria como um pipeline . Isso deixa o usuário com a opção de usar qualquer "pré-processador" ou "linguagem de script" com a qual ele esteja mais familiarizado.
(você precisa confiar no usuário sobre problemas de segurança se aceitar uma configuração dinamicamente calculada)
Portanto, no seu código de inicialização, você main
(por exemplo) aceitaria algum --config
argumento confarg
e obteria FILE*configf;
dele. Se esse argumento começar com !
(ou seja, se (confarg[0]=='!')
....), você usaria configf = popen(confarg+1, "r");
e fecharia esse pipe com pclose(configf);
. Caso contrário, você usaria configf=fopen(confarg, "r");
e fecharia esse arquivo fclose(configf);
(não se esqueça da verificação de erros). Veja tubo (7) , tampa (3) , tampa (3) . Para uma aplicação codificada em Python leia sobre os.popen , etc ...
(documento também para o usuário estranho que deseja passar um arquivo de configuração nomeado !foo.config
para passar ./!foo.config
para ignorar o popen
truque acima)
BTW, esse truque é apenas uma conveniência (para evitar exigir que o usuário avançado codifique, por exemplo, algum shell script para gerar um arquivo de configuração ). Se o usuário desejar relatar algum bug, ele deverá enviar o arquivo de configuração gerado ...
Observe que você também pode projetar seu aplicativo com a capacidade de usar e carregar plugins no momento da inicialização, por exemplo, com dlopen (3) (e você precisa confiar no usuário sobre esse plug-in). Novamente, essa é uma decisão arquitetural muito importante (e você precisa definir e fornecer alguma API e convenção bastante estável sobre esses plug-ins e seu aplicativo).
Para um aplicativo codificado em uma linguagem de script como Python, você também pode aceitar algum argumento de programa para eval ou exec ou primitivas similares. Novamente, os problemas de segurança são a preocupação do usuário (avançado) .
Em relação ao formato textual do seu arquivo de configuração (gerado ou não), acredito que você precisa documentá-lo bem (e a escolha de um formato específico não é tão importante; no entanto, recomendo que seu usuário possa colocar alguns comentários ignorados). Você pode usar JSON (de preferência com algum analisador JSON aceitando e pulando comentários com o uso normal //
até eol ou /*
... */
...), ou YAML, XML ou INI ou suas próprias coisas. A análise de um arquivo de configuração é razoavelmente fácil (e você encontrará muitas bibliotecas relacionadas a essa tarefa).