Quão ruim de idéia é usar arquivos Python como arquivos de configuração?

72

Eu sempre usei arquivos JSON para configuração dos meus aplicativos. Comecei a usá-los quando codifiquei muito Java e agora estou trabalhando principalmente no desenvolvimento de Python no lado do servidor e na ciência de dados e não tenho certeza se o JSON é o caminho certo a seguir.

Eu vi o Celery usar arquivos Python reais para configuração. Inicialmente fiquei cético sobre isso. Mas a ideia de usar estruturas de dados Python simples para configuração está começando a crescer em mim. Alguns profissionais:

  • As estruturas de dados serão as mesmas que eu normalmente codifico. Portanto, não preciso mudar de ideia.
  • Meu IDE (PyCharm) entende a conexão entre configuração e código. Ctrl+ Btorna possível alternar facilmente entre configuração e código.
  • Não preciso trabalhar com o JSON estrito desnecessário da IMO . Estou olhando para você aspas duplas, sem vírgulas e sem comentários.
  • Posso escrever configurações de teste no aplicativo em que estou trabalhando e depois transportá-las facilmente para um arquivo de configuração sem precisar fazer nenhuma conversão e análise JSON.
  • É possível criar scripts muito simples no arquivo de configuração, se realmente necessário. (Embora isso deva ser muito, muito limitado.)

Então, minha pergunta é: se eu trocar, como vou me dar um tiro no pé?

Nenhum usuário final não qualificado usará os arquivos de configuração. No momento, quaisquer alterações nos arquivos de configuração são confirmadas no Git e lançadas em nossos servidores como parte da implantação contínua. Não há alterações manuais na configuração, a menos que haja uma emergência ou ela esteja em desenvolvimento.

(Eu considerei o YAML , mas algo me irrita. Então, por enquanto, está fora da mesa americana.)

André Christoffer Andersen
fonte
39
Não qualificado não é seu problema. Malicioso é.
Blrfl
9
O que você quer dizer com "fora da mesa americana" ?
Peter Mortensen
24
"Então, por enquanto está fora da mesa americana." === "Então, por enquanto, como dizem os americanos, está fora da mesa."
bispo
7
Se você não gosta do JSON, tente o yaml. Eu gosto muito de configurações. especialmente quando cadeias maiores estão envolvidas, o YAML fica mais legível que o JSON.
Christian Sauer
5
@bishop "fora da mesa" no inglês britânico significa que não está mais em consideração, pois moções parlamentares são colocadas sobre a mesa no meio da Câmara dos Comuns para referência quando estão sendo discutidas e, portanto, também 'apresentadas para discussão' (registro parlamentar 1799 - books.google.co.uk/… ), AFAIK o significado dos EUA é o mesmo, mas não sei se você tem uma mesa no seu parlamento.
precisa

Respostas:

92

Usando uma linguagem de script no lugar de um arquivo de configuração parece ótimo à primeira vista: você tem todo o poder de que a linguagem disponível e pode simplesmente eval()ou importele. Na prática, existem algumas dicas:

  • é uma linguagem de programação que precisa ser aprendida. Para editar a configuração, você precisa conhecer esse idioma suficientemente bem. Os arquivos de configuração geralmente têm um formato mais simples, mais difícil de errar.

  • é uma linguagem de programação, o que significa que a configuração pode ficar difícil de depurar. Com um arquivo de configuração normal, você olha para ele e vê quais valores são fornecidos para cada propriedade. Com um script, você potencialmente precisará executá-lo primeiro para ver os valores.

  • é uma linguagem de programação, o que dificulta a manutenção de uma separação clara entre a configuração e o programa real. Às vezes, você deseja esse tipo de extensibilidade, mas nesse ponto provavelmente está procurando um sistema de plug-ins real.

  • é uma linguagem de programação, o que significa que a configuração pode fazer qualquer coisa que a linguagem de programação possa fazer. Então, você está usando uma solução sandbox que nega grande parte da flexibilidade do idioma ou está confiando muito no autor da configuração.

Portanto, é provável que o uso de um script para configuração seja bom se o público da sua ferramenta for desenvolvedor, por exemplo, Sphinx config ou o setup.py em projetos Python. Outros programas com configuração executável são shells como o Bash e editores como o Vim.

O uso de uma linguagem de programação para configuração é necessário se a configuração contiver muitas seções condicionais ou se fornecer retornos de chamada / plug-ins. Usar um script diretamente em vez de eval () - algum campo de configuração tende a ser mais debugável (pense nos rastreamentos da pilha e nos números de linha!).

Usar diretamente uma linguagem de programação também pode ser uma boa idéia se sua configuração for tão repetitiva que você estiver escrevendo scripts para gerar automaticamente a configuração. Mas talvez um modelo de dados melhor para a configuração possa remover a necessidade de tal configuração explícita? Por exemplo, pode ser útil se o arquivo de configuração puder conter espaços reservados que você expandir posteriormente. Outro recurso visto às vezes são vários arquivos de configuração com precedência diferente que podem se sobrepor, embora isso introduza alguns problemas.

Na maioria dos casos, arquivos INI, arquivos de propriedades Java ou documentos YAML são muito mais adequados para configuração. Para modelos de dados complexos, o XML também pode ser aplicável. Como você observou, o JSON tem alguns aspectos que o tornam inadequado como um arquivo de configuração editável por humanos, embora seja um bom formato de troca de dados.

amon
fonte
25
Existem alguns formatos de arquivo de configuração que são "acidentalmente concluídos em Turing", mais famosos sendmail.cf. Isso indicaria que o uso de uma linguagem de script real pode ser benéfica, pois essa foi realmente projetada para ser completa em Turing. No entanto , Turing-completeness e "Tetris-completeness" são duas coisas diferentes e, embora sendmail.cfpossam computar funções arbitrárias, ele não pode enviar sua /etc/passwdatravés da rede ou formatar seu disco rígido, o que Python ou Perl seriam capazes.
Jörg W Mittag
3
@ JörgWMittag Turin-completness não implica poder enviar coisas pela rede ou acessar o disco rígido. Ou seja, a completude de Turim é sobre processamento e não sobre E / S. Por exemplo, o CSS é considerado Turim completo, mas não interfere no seu armazenamento permanente. Você disse em outro lugar que "Idris é uma linguagem funcional pura e total, por definição, não é Turing-completa", que não segue, e aparentemente é Turim completa. Eu estava convencido de que o uso do Testris-complete significava que o idioma estava completo em Turim, mas não era capaz de fazer E / S completa ... parece que não é isso que você quer dizer.
Theraot
6
@ Theraot: "Total" significa que sempre retorna. Uma máquina de Turing pode executar um loop infinito, ou seja, tem a capacidade de não retornar. Portanto, Idris não pode fazer tudo o que uma máquina de Turing faz, o que significa que ela não é completa em Turing. Isso vale para todos os idiomas de tipo dependente. O ponto principal de uma linguagem de tipo dependente é que você pode decidir propriedades arbitrárias sobre programas, enquanto que em uma linguagem completa de Turing você não pode nem mesmo decidir propriedades triviais como "este programa é interrompido?" Por definição, os idiomas totais não são completos para Turing, porque as Máquinas de Turing são parciais.
Jörg W Mittag
10
A definição de "Turing-complete" é "pode ​​implementar uma máquina de Turing". A definição de "Tetris-complete" é "pode ​​implementar o Tetris". O ponto principal dessa definição é que a completude de Turing simplesmente não é muito interessante no mundo real. Existem muitas linguagens úteis que não são completas de Turing, por exemplo, HTML, SQL (pré-1999), várias DSLs, etc. OTOH, completeza de Turing apenas implica que você pode calcular funções em números naturais, isso não implica impressão na tela, acesso à rede, interação com o usuário, o sistema operacional, o ambiente, todos importantes.
Jörg W Mittag
4
A razão pela qual Edwin Brady usou esse exemplo é porque muitas pessoas pensam que linguagens que não são completas em Turing não podem ser usadas para programação de uso geral. Eu também costumava pensar que, já que, afinal, muitos programas interessantes são loops infinitos que não queremos parar , por exemplo, servidores, sistemas operacionais, loops de eventos em uma GUI, loops de jogos. Muitos programas processam dados infinitos, por exemplo, fluxos de eventos. Eu costumava pensar que você não pode escrever isso em um idioma total, mas desde então aprendi que é possível e, portanto, acho uma boa idéia ter um termo para esse recurso.
Jörg W Mittag
50

+1 em tudo na resposta de amon . Eu gostaria de adicionar isto:

Você se arrependerá de usar o código Python como idioma de configuração na primeira vez que desejar importar a mesma configuração de dentro do código escrito em um idioma diferente. Por exemplo, se o código que faz parte do seu projeto e escrito em C ++ ou Ruby ou algo mais precisar puxar a configuração, será necessário vincular o interpretador Python como uma biblioteca ou analisar a configuração em um coprocesso Python, ambos que são difíceis, difíceis ou de alto custo.

Todo o código que importa essa configuração hoje pode ser escrito em Python, e você pode pensar que isso também será verdade amanhã, mas você tem certeza?

Você disse que usaria lógica (qualquer outra coisa que não estruturas de dados estáticas) em sua configuração com moderação, o que é bom, mas se houver algo disso, será difícil no futuro desfazê-lo para que você pode voltar para um arquivo de configuração declarativo.

EDIT para o registro: várias pessoas comentaram sobre esta resposta sobre a probabilidade ou a probabilidade de um projeto ser completamente reescrito com sucesso em outro idioma. É justo dizer que uma reescrita completa compatível com versões anteriores raramente é vista. O que eu realmente tinha em mente eram partes do mesmo projeto (e que precisavam de acesso à mesma configuração) sendo escritas em diferentes idiomas. Por exemplo, servindo pilha em C ++ para velocidade, limpeza de banco de dados em lote em Python, alguns scripts de shell como cola. Então pense também nesse caso :)

Celada
fonte
11
@Mast, desculpas, mas eu não sigo. O nome do arquivo (independentemente de terminar ou não em .py) não está aqui nem ali. O ponto que estou tentando enfatizar é que, se estiver escrito em Python, você precisará de um intérprete para lê-lo.
Celada
12
@ Mas eu acho que você está analisando errado. O argumento que tirei dessa resposta (original e editada) é que a opção de gravar arquivos de configuração em uma linguagem de programação é que torna mais difícil escrever código em outra linguagem. Por exemplo, você decide portar seu aplicativo para o Anrdoid / iPhone e usará outro idioma. Você precisa (a) confiar em um intérprete Python no aplicativo para celular (não é o ideal), (b) reescrever a configuração em um formato independente da linguagem e reescrever o código Python que a usou, ou (c) manter dois formatos de configuração daqui para frente.
Jon Bentley
4
@ JonBentley Suponho que a preocupação será relevante se houver planos de realizar projetos em vários idiomas. Eu não tive essa impressão do OP. Além disso, o uso de arquivos de texto para configuração ainda requer código adicional (em todos os idiomas) para análise / conversão de valores reais. Tecnicamente, se eles limitam o lado do Python a key=valueatribuições para a configuração, não vejo por que um programa Java / C ++ não pôde ler o arquivo Python como um arquivo de texto sem formatação e analisá-lo da mesma forma, se precisar passar para outra coisa em o futuro. Não vejo necessidade de um intérprete de Python completo.
code_dredd
3
@ray True, mas a resposta ainda é útil com base no fato de que as perguntas não devem ser aplicáveis ​​apenas à pessoa que as publica. Se você usar um formato padronizado (por exemplo, INI, JSON, YAML, XML, etc.), provavelmente usará uma biblioteca de análise existente em vez de criar sua própria. Isso reduz o trabalho adicional a apenas uma classe de adaptador para interagir com a biblioteca de análise. Se você está se limitando a key = value, isso acaba com a maioria dos motivos do OP para usar o Python em primeiro lugar e você também pode optar por um formato reconhecido.
Jon Bentley
3
Eu tive que fazer isso alguns anos atrás, quando uma ferramenta escrita em Lua usava o script Lua como suas configurações, então eles queriam que escrevêssemos uma nova ferramenta em C # e nos pediram especificamente para usar o script de configuração Lua. Eles tinham um total de 2 linhas que eram realmente programáveis ​​e não eram simples x = y, mas eu ainda tinha que aprender sobre os intérpretes de código aberto Lua para .net por causa deles. Não é um argumento puramente teórico.
Kevin Fee
21

As outras respostas já são muito boas, trarei minha experiência de uso no mundo real em alguns projetos.

Prós

Eles já estão detalhados:

  • se você estiver em um programa Python, a análise é fácil ( eval); funciona automaticamente mesmo para tipos de dados mais complexos (em nosso programa, temos pontos e transformações geométricas, que são despejadas / carregadas com precisão repr/ eval);
  • criar uma "configuração falsa" com apenas algumas linhas de código é trivial;
  • você tem estruturas melhores e, na IMO, sintaxe muito melhor que o JSON (caramba, mesmo tendo apenas comentários e não ter que colocar aspas duplas em torno das chaves do dicionário é uma grande vitória de legibilidade).

Contras

  • usuários mal-intencionados podem fazer qualquer coisa que seu programa principal possa fazer; Não considero isso um grande problema, pois, geralmente, se um usuário pode modificar um arquivo de configuração, ele já pode fazer o que o aplicativo pode;
  • Se você não está mais em um programa Python, agora você tem um problema. Enquanto vários de nossos arquivos de configuração permaneceram privados do aplicativo original, um em particular veio para armazenar informações usadas por vários programas diferentes, a maioria dos quais atualmente em C ++, que agora possui um analisador de hackers para um pequeno e mal definido subconjunto do Python repr. Obviamente, isso é uma coisa ruim.
  • Mesmo que seu programa permaneça em Python, você pode alterar a versão do Python. Digamos que seu aplicativo foi iniciado no Python 2; depois de muitos testes, você conseguiu migrá-lo para o Python 3 - infelizmente, você realmente não testou todo o seu código - você tem todos os arquivos de configuração nas máquinas dos seus clientes, escritos para o Python 2 e nos quais você não realmente tem controle. Você não pode nem fornecer um "modo de compatibilidade" para ler arquivos de configuração antigos (o que geralmente é feito para formatos de arquivo), a menos que você esteja disposto a agrupar / ligar para o intérprete Python 2!
  • Mesmo se você estiver no Python, modificar o arquivo de configuração do código é um problema real, porque ... bem, a modificação do código não é trivial, especialmente o código que possui uma sintaxe rica e não está no LISP ou similar. Um programa nosso tem um arquivo de configuração que é Python, originalmente escrito à mão, mas que mais tarde resultou que seria útil manipular via software (uma configuração específica é uma lista de coisas que são muito mais fáceis de reordenar usando uma GUI). Este é um grande problema, porque:

    • até mesmo realizar uma análise → AST → reescrever ida e volta não é trivial (você notará que metade das soluções propostas são posteriormente marcadas como "obsoletas, não use, não funciona em todos os casos");
    • mesmo se eles funcionassem, o AST é muito baixo; você geralmente está interessado em manipular o resultado dos cálculos realizados no arquivo, não as etapas que o trouxeram;
    • o que nos leva ao simples fato de que você não pode apenas editar os valores com os quais está interessado, porque eles podem ser gerados por algum cálculo complexo que você não pode entender / manipular através do seu código.

    Compare isso com JSON, INI ou (Deus não permita!) XML, onde a representação na memória sempre pode ser editada e gravada sem perda de dados (XML, onde a maioria dos analisadores DOM pode manter espaço em branco nos nós de texto e nos comentários) ou pelo menos perdendo apenas alguma formatação (JSON, onde o formato em si não permite muito mais do que os dados brutos que você está lendo).


Portanto, como sempre, não há uma solução clara; minha política atual sobre o assunto é:

  • se o arquivo de configuração for:

    • certamente para um aplicativo Python e privado para ele - como em ninguém mais tentará ler nele;
    • escrito a mão;
    • provenientes de uma fonte confiável;
    • usar tipos de dados de aplicativo de destino é realmente um prêmio;

    um arquivo Python pode ser uma ideia válida;

  • se em vez disso:

    • pode haver a possibilidade de ler algum outro aplicativo;
    • existe a possibilidade de que este arquivo possa ser editado por um aplicativo, possivelmente até o meu próprio aplicativo;
    • é fornecida por uma fonte não confiável.

    um formato "apenas dados" pode ser uma ideia melhor.

Observe que não é necessário fazer uma única escolha - recentemente escrevi um aplicativo que usa as duas abordagens. Eu tenho um arquivo quase nunca modificado com configurações manuscritas de primeira instalação, nas quais há vantagens em ter ótimos bônus em Python e um arquivo JSON para configuração editado a partir da interface do usuário.

Matteo Italia
fonte
11
ponto muito bom sobre como gerar ou reescrever a configuração! Porém, poucos formatos diferentes de XML podem reter comentários na saída, que considero extremamente importantes para a configuração. Outros formatos às vezes introduzem um note:campo que é ignorado para a configuração.
amon
2
"se um usuário pode modificar um arquivo de configuração, ele já pode fazer o que o aplicativo pode fazer" - isso não é bem verdade. Que tal testar um arquivo de configuração brilhante que alguém que você não conhece tenha carregado no pastebin?
Dmitry Grigoryev
2
@DmitryGrigoryev: se você está apontando para esse alvo, pode também pedir à sua vítima para copiar e colar alguns curl ... | bash, é ainda menos complicado. :-P
Matteo Italia
@DmitryGrigoryev: e é o tipo de coisa que pode permitir que alguém destrua completamente um sistema de produção no primeiro dia de trabalho. Se 'eval' for seu analisador, isso significa que não há oportunidade de verificar se há problemas antes de ser lido. (a mesma razão pela qual os scripts shell são tão ruins na produção). INI, YAML ou JSON são seguros a esse respeito.
21417 Joe
11
@DmitryGrigoryev: o que quero dizer é que, se o seu tipo de vítima é estúpido o suficiente para copiar e colar cegamente um arquivo de configuração, você provavelmente pode induzi-lo a fazer o que quer que seja na máquina com métodos menos oblíquos ("cole-o em um console para corrija seu problema! "). Além disso, mesmo com arquivos de configuração não executáveis, há muito potencial para causar danos - mesmo apontando maliciosamente o log de arquivos críticos (se o aplicativo for executado com privilégios suficientes), você poderá causar estragos no sistema. Essa é a razão pela qual acho que, na prática, não há muita diferença em termos de segurança.
Matteo Italia
8

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.configpara passar ./!foo.configpara ignorar o popentruque 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).

Basile Starynkevitch
fonte
+1 por mencionar a integridade de Turing das linguagens de programação. Alguns trabalhos interessantes revelam que limitar o poder computacional do formato de entrada é essencial para garantir a camada de manipulação de entrada. O uso de uma linguagem de programação completa de Turing segue na direção oposta.
Matheus Moreira
2

Adicionando à resposta de amon , você considerou alternativas? Talvez o JSON seja mais do que você precisa, mas os arquivos Python provavelmente apresentarão problemas no futuro pelos motivos mencionados acima.

No entanto, o Python já possui um analisador de configuração para uma linguagem de configuração muito simples que pode atender a todas as suas necessidades. O ConfigParsermódulo implementa uma linguagem de configuração simples.

CodeMonkey
fonte
11
Usar algo 'semelhante a ... arquivos INI do Microsoft Windows' parece ser uma péssima idéia, tanto porque não é um formato particularmente flexível quanto porque 'similar' implica incompatibilidades não documentadas.
Pete Kirkham
11
@PeteKirkham Bem, é simples, está documentado e faz parte da biblioteca padrão do Python. Pode ser a solução perfeita para as necessidades dos OPs, porque ele está procurando por algo que seja suportado diretamente pelo Python e mais simples que o JSON. Enquanto ele não especificar mais quais são suas necessidades, acho que essa resposta pode ser útil para ele.
codemonkey
11
Eu sugeriria basicamente isso - veja quais tipos de arquivos de configuração as bibliotecas Python suportam e escolha um deles. Além disso, o Powershell possui a noção de seções de dados - que permitem construções limitadas da linguagem do Powershell - protegendo contra códigos maliciosos. Se o Python tiver uma biblioteca que ofereça suporte a um subconjunto limitado do Python para configuração, isso atenua pelo menos um dos contras da idéia no OP.
Χpẘ
11
@PeteKirkham É mais provável que seja um problema ao contrário. O Windows tende a ter um monte de porcaria não documentada que explode em você. Python tende a ser bem documentado e direto. Dito isto, se você só precisa de pares simples de chave / valor ( talvez com seções), é uma boa escolha. Eu suspeito que isso cubra 90% dos casos de uso. Se os arquivos de configuração do .NET fossem ini em vez do monstruoso XML com um esquema que na verdade é mascarado de código como config, todos estaríamos muito melhor.
jpmc26
11
@PeteKirkham Na verdade não. Sendo o INI o melhor para casos de uso simples, é possível que você evite incompatibilidades. Eles também não importam se você não está consumindo o arquivo com dois idiomas diferentes e, mesmo que esteja, provavelmente poderá encontrar implementações abertas em qualquer idioma (permitindo que você não tenha incompatibilidades ou, no mínimo, saiba exatamente o que eles são). Concordo que você deve usar outro formato se o seu caso de uso for realmente complexo o suficiente para você começar a encontrá-los ou se não conseguir encontrar uma implementação existente em que possa confiar, mas isso não é comum.
jpmc26
1

Eu trabalhei por um longo tempo com algum software conhecido que tem seus arquivos de configuração escritos em TCL, então a idéia não é nova. Isso funcionou muito bem, já que os usuários que não conheciam o idioma ainda podiam escrever / editar arquivos de configuração simples usando uma única set name valuedeclaração, enquanto usuários e desenvolvedores mais avançados podiam usar truques sofisticados com isso.

Eu não acho que "os arquivos de configuração podem ficar difíceis de depurar" é uma preocupação válida. Desde que seu aplicativo não force os usuários a escrever scripts, eles sempre poderão usar atribuições simples em seus arquivos de configuração, o que dificilmente será mais difícil de acertar em comparação com JSON ou XML.

Reescrever a configuração é um problema, embora não seja tão ruim quanto parece. Atualizar código arbitrário é impossível, mas carregar a configuração de um arquivo, alterá-lo e salvá-lo novamente. Basicamente, se você criar algum script em um arquivo de configuração que não seja somente leitura, você acabará com uma lista equivalente de set name valueinstruções assim que ela for salva. Uma boa dica de que isso acontecerá é um comentário "não edite" no início do arquivo.

Uma coisa a considerar é que seus arquivos de configuração não serão legíveis de forma confiável por ferramentas simples baseadas em regex, como sed, mas até onde eu entendo, esse já não é o caso dos seus arquivos JSON atuais, portanto, não há muito a perder.

Apenas certifique-se de usar técnicas apropriadas de sandbox ao executar seus arquivos de configuração.

Dmitry Grigoryev
fonte
11
"Software" é um substantivo incontável, portanto deve ser " algum software bem conhecido".
jpmc26
1

Além de todos os pontos válidos de outras boas respostas aqui (uau, eles até mencionaram o conceito Turing-complete), na verdade existem algumas razões práticas sólidas para NÃO usar um arquivo Python como sua configuração, mesmo quando você estiver trabalhando em um Python- único projeto.

  1. As configurações dentro de um arquivo de origem Python são tecnicamente parte do código-fonte executável, em vez de um arquivo de dados somente leitura. Se você seguir essa rota, normalmente faria isso import config, porque esse tipo de "conveniência" provavelmente foi um dos principais motivos pelos quais as pessoas começaram a usar um arquivo Python como configuração em primeiro lugar. Agora você tende a confirmar esse config.py em seu repositório, caso contrário, o usuário final encontrará um ImportError confuso ao tentar executar o programa pela primeira vez.

  2. Supondo que você realmente confirme esse config.py em seu repositório, agora os membros da sua equipe provavelmente terão configurações diferentes em ambientes diferentes. Imagine que algum dia algum membro comprometa acidentalmente seu arquivo de configuração local no repositório.

  3. Por último, mas não menos importante, seu projeto pode ter senhas no arquivo de configuração. (Essa é uma prática discutível por si só, mas acontece de qualquer maneira.) E se o seu arquivo de configuração existir no repositório, você corre o risco de comprometer sua credencial em um repositório público.

Agora, o uso de um arquivo de configuração somente de dados, como o formato JSON universal, pode evitar todos os 3 problemas acima, porque você pode razoavelmente pedir ao usuário que crie seu próprio config.json e o alimente no seu programa.

PS: É verdade que o JSON tem muitas restrições. 2 das limitações mencionadas no OP podem ser resolvidas com alguma criatividade.

RayLuo
fonte