Quelle est l'idée d'une mauvaise idée d'utiliser des fichiers Python en tant que fichiers de configuration?

72

J'ai toujours utilisé des fichiers JSON pour la configuration de mes applications. J'ai commencé à les utiliser à partir du moment où je codais beaucoup de Java. Aujourd'hui, je travaille principalement sur le développement Python côté serveur et en science des données, et je ne suis pas sûr que JSON soit la bonne solution.

J'ai vu Celery utiliser des fichiers Python réels pour la configuration. Au début, j'étais sceptique à ce sujet. Mais l'idée d'utiliser de simples structures de données Python pour la configuration commence à germer. Quelques pros:

  • Les structures de données seront les mêmes que celles que je code normalement. Je n'ai donc pas besoin de changer d'état d'esprit.
  • Mon IDE (PyCharm) comprend le lien entre la configuration et le code. Ctrl+ Bpermet de basculer facilement entre la configuration et le code.
  • Je n'ai pas besoin de travailler avec JSON strict strict inutile IMO . Je vous regarde entre guillemets, sans virgule ni commentaire.
  • Je peux écrire des configurations de test dans l'application sur laquelle je travaille, puis les transférer facilement dans un fichier de configuration sans avoir à effectuer de conversion ni d'analyse JSON.
  • Il est possible de faire un script très simple dans le fichier de configuration si vraiment nécessaire. (Bien que cela devrait être très très limité.)

Ma question est donc la suivante: si je change de mode, comment puis-je me tirer une balle dans le pied?

Aucun utilisateur final non qualifié n'utilisera les fichiers de configuration. Toutes les modifications apportées aux fichiers de configuration sont actuellement validées dans Git et sont déployées sur nos serveurs dans le cadre d'un déploiement continu. Il n'y a pas de changement de configuration manuel, sauf en cas d'urgence ou de développement.

(J'ai envisagé YAML , mais quelque chose à ce sujet m'énerve. Donc, pour l'instant, c'est hors de la table américaine.)

André Christoffer Andersen
la source
39
La non-qualifiée n'est pas votre problème. Malicieux est.
Blrfl
9
Qu'entendez-vous par "hors de la table américaine" ?
Peter Mortensen
24
"Donc, pour l'instant, c'est hors de la table américaine." === "Donc, pour l'instant, comme le dit l'Américain, il est hors de propos."
évêque
7
Si vous n'aimez pas JSON, vous devriez essayer yaml. Je l'aime beaucoup pour les configs. En particulier lorsque de plus grandes chaînes sont impliquées, YAML est plus lisible que JSON.
Christian Sauer
5
@bishop "off the table" en anglais britannique ne signifie plus, les motions parlementaires ayant été déposées au centre de la Chambre des communes comme référence lors de la discussion, donc aussi "déposées pour discussion" (compte rendu parlementaire 1799 - books.google.co.uk/… ), autant que je sache, la signification des États-Unis est la même, mais je ne sais pas si vous avez une table dans votre parlement.
Pete Kirkham

Réponses:

92

L' utilisation d' un langage de script en place d'un fichier de configuration ressemble beaucoup au premier coup d' œil: vous avez la pleine puissance de cette langue disponible et peut simplement eval()ou importelle. En pratique, il y a quelques pièges:

  • c'est un langage de programmation qui doit être appris. Pour éditer la configuration, vous devez connaître suffisamment cette langue. Les fichiers de configuration ont généralement un format plus simple et plus difficile à obtenir.

  • c'est un langage de programmation, ce qui signifie que la configuration peut être difficile à déboguer. Avec un fichier de configuration normal, examinez-le et voyez quelles valeurs sont fournies pour chaque propriété. Avec un script, vous devez éventuellement l'exécuter pour voir les valeurs.

  • c'est un langage de programmation, ce qui rend difficile de maintenir une séparation claire entre la configuration et le programme réel. Parfois, vous souhaitez ce type d'extensibilité, mais à ce stade, vous recherchez probablement plutôt un véritable système de plug-in.

  • c'est un langage de programmation, ce qui signifie que la configuration peut faire tout ce que le langage de programmation peut faire. Donc, soit vous utilisez une solution de sandbox qui nie une grande partie de la flexibilité du langage, soit vous accordez une grande confiance à l'auteur de la configuration.

Donc, utiliser un script pour la configuration est probablement OK si le public de votre outil est constitué de développeurs, par exemple Sphinx config ou le fichier setup.py dans les projets Python. D'autres programmes avec une configuration exécutable sont des shells comme Bash et des éditeurs comme Vim.

L'utilisation d'un langage de programmation pour la configuration est nécessaire si la configuration contient de nombreuses sections conditionnelles, ou si elle fournit des rappels / plugins. Utiliser un script directement au lieu de eval () - certains champs de configuration ont tendance à être plus faciles à déboguer (pensez aux traces de pile et aux numéros de ligne!).

L'utilisation directe d'un langage de programmation peut également être une bonne idée si votre configuration est tellement répétitive que vous écrivez des scripts pour générer automatiquement la configuration. Mais peut-être qu'un meilleur modèle de données pour la configuration pourrait supprimer la nécessité d'une telle configuration explicite? Par exemple, il peut être utile que le fichier de configuration puisse contenir des espaces réservés que vous développez ultérieurement. Une autre caractéristique parfois observée est la présence de plusieurs fichiers de configuration avec une priorité différente pouvant se remplacer, bien que cela pose certains problèmes.

Dans la plupart des cas, les fichiers INI, les fichiers de propriétés Java ou les documents YAML conviennent beaucoup mieux à la configuration. Pour les modèles de données complexes, XML peut également être applicable. Comme vous l'avez noté, JSON présente certains aspects qui le rendent inutilisable en tant que fichier de configuration modifiable par l'homme, même s'il s'agit d'un format d'échange de données précis.

Amon
la source
25
Il existe quelques formats de fichiers de configuration qui sont "accidentellement Turing-complete", le plus connu sendmail.cf. Cela indiquerait que l'utilisation d'un langage de script réel pourrait être bénéfique, étant donné que celui-ci a été conçu pour être complet. Cependant , la complétude de Turing et la "complétude de Tetris" sont deux choses différentes, et bien sendmail.cfqu’elles puissent calculer des fonctions arbitraires, elles ne peuvent pas vous envoyer /etc/passwdsur le net ni formater votre disque dur, ce que Python ou Perl seraient en mesure de le faire.
Jörg W Mittag
3
@ JörgWMittag Turin-complet n'implique pas la possibilité d'envoyer des choses sur le réseau ou d'accéder au disque dur. En d'autres termes, Turin-complétness concerne le traitement et non les entrées / sorties. Par exemple, CSS est considéré comme complet à Turin, mais il ne gâchera pas votre stockage permanent. Vous avez dit ailleurs que "Idris est un langage purement fonctionnel, donc, par définition, il ne s'agit pas de Turing-complete", cela ne suit pas, et apparemment, c'est Turin complet. J'étais convaincue que votre utilisation de Testris-complete signifiait que la langue était complète mais que vous ne pouviez pas effectuer une E / S complète ... il semble que ce ne soit pas ce que vous voulez dire.
Theraot
6
@Theraot: "Total" signifie qu'il revient toujours. Une machine de Turing peut effectuer une boucle infinie, c'est-à-dire qu'elle a la capacité de ne pas revenir. Ainsi, Idris ne peut pas faire tout ce qu'une machine de Turing fait, ce qui signifie qu'elle n'est pas complète. Cela est vrai de tous les langages à caractères dépendants. L'intérêt d'un langage typé de manière dépendante est que vous pouvez décider des propriétés arbitraires des programmes, alors que dans un langage complet de Turing, vous ne pouvez même pas choisir des propriétés triviales telles que "ce programme est-il interrompu?" Le total des langues ne sont par définition pas Turing-complete, car les machines de Turing sont partielles.
Jörg W Mittag
10
La définition de "Turing-complete" est "peut implémenter une machine de Turing". La définition de "Tetris-complet" est "peut implémenter Tetris". Le but de cette définition est que la complétude de Turing n’est tout simplement pas très intéressante dans le monde réel. Il existe de nombreux langages utiles qui ne sont pas complets avec Turing, par exemple HTML, SQL (avant 1999), divers DSL, etc. imprimer à l'écran, accéder au réseau, interagir avec l'utilisateur, le système d'exploitation, l'environnement, qui sont tous importants.
Jörg W Mittag
4
Edwin Brady a utilisé cet exemple parce que beaucoup de gens pensent que les langages qui ne sont pas Turing-complete ne peuvent pas être utilisés pour de la programmation à usage général. J'avais moi-même l'habitude de penser cela aussi, car après tout, de nombreux programmes intéressants sont essentiellement des boucles sans fin que nous ne voulons pas arrêter , par exemple des serveurs, des systèmes d'exploitation, des boucles d'événement dans une interface graphique, des boucles de jeu. Beaucoup de programmes traitent des données infinies, par exemple des flux d'événements. Je pensais que vous ne pouvez pas écrire que dans une langue totale, mais j'appris depuis que vous pouvez , et je trouve une bonne idée d'avoir un terme pour cette capacité.
Jörg W Mittag
50

+1 à tout dans la réponse amon . J'aimerais ajouter ceci:

Vous regretterez d'utiliser le code Python comme langue de configuration la première fois que vous souhaitez importer la même configuration à partir d'un code écrit dans une langue différente. Par exemple, si le code faisant partie de votre projet et écrit en C ++ ou en Ruby ou si quelque chose d’autre doit extraire la configuration, vous devez créer un lien dans l’interpréteur Python en tant que bibliothèque ou analyser la configuration dans un coprocessus Python. qui sont maladroites, difficiles, ou à haute surcharge.

Tout le code qui importe cette configuration aujourd'hui peut être écrit en Python, et vous pensez peut-être que ce sera le cas demain également, mais êtes-vous certain?

Vous avez dit que vous utiliseriez avec parcimonie la logique (quelque chose d’autre que des structures de données statiques) dans votre configuration, ce qui est bien, mais si vous en rencontrez un, vous aurez du mal à le défaire à l’avenir pour peut revenir à un fichier de configuration déclaratif.

EDIT for the record: plusieurs personnes ont commenté cette réponse sur la probabilité ou l’improbabilité qu’un projet soit réécrit complètement avec succès dans une autre langue. Il est juste de dire qu’une réécriture intégrale compatible avec les versions antérieures est probablement rarement vue. Ce que je pensais réellement, c’était des morceaux d’un même projet (et qui nécessitaient un accès à la même configuration) étant écrits dans différentes langues. Par exemple, servir la pile en C ++ pour la rapidité, nettoyer la base de données par lots en Python, utiliser certains scripts shell. Alors réfléchissez bien à cette affaire aussi :)

Celada
la source
1
@Mast, excusez-moi, mais je ne vous suis pas. Le nom du fichier (qu'il se termine ou non par .py) n'est ni ici ni là-bas. Ce que j'essaie de dire, c'est que si c'est écrit en Python, vous avez besoin d'un interpréteur Python pour le lire.
Celada
12
@Mast, je pense que vous l'avez mal interprété. L’argument que j’ai retenu de cette réponse (originale et modifiée) est que le choix d’écrire des fichiers de configuration dans un langage de programmation est qu’il est plus difficile d’écrire du code dans un autre langage. Par exemple, vous décidez de porter votre application sur Anrdoid / iPhone et utiliserez une autre langue. Vous devez soit (a) compter sur un interpréteur Python sur l’application de téléphonie mobile (pas idéal), (b) réécrire la configuration dans un format indépendant de la langue et réécrire le code Python qui l’a utilisée, ou (c) maintenir deux formats de configuration à venir.
Jon Bentley
4
@JonBentley Je suppose que l'inquiétude sera pertinente s'il est prévu de réaliser des projets multilingues. Je n'ai pas eu cette impression de l'OP. De plus, l'utilisation de fichiers texte pour la configuration nécessite toujours du code supplémentaire (dans toutes les langues) pour l'analyse / conversion réelle des valeurs. Techniquement, s’ils limitent le côté Python à des key=valueassignations pour la configuration, je ne vois pas pourquoi un programme Java / C ++ ne pourrait pas lire le fichier Python en tant que fichier texte brut et l’analyser de la même manière s’ils doivent passer à autre chose l'avenir. Je ne vois pas la nécessité d'un interprète Python à part entière.
code_dredd
3
@ray True, mais la réponse est toujours utile car les questions ne doivent pas être uniquement applicables à la personne qui les publie. Si vous utilisez un format normalisé (par exemple, INI, JSON, YAML, XML, etc.), vous utiliserez probablement une bibliothèque d'analyse syntaxique existante plutôt que d'écrire votre propre. Cela réduit le travail supplémentaire à seulement une classe d'adaptateur pour interfacer avec la bibliothèque d'analyse. Si vous vous limitez à la valeur clé = valeur, la plupart des raisons pour lesquelles le PO n'utilise pas Python sont alors éliminées. Vous pouvez également utiliser un format reconnu.
Jon Bentley
3
Je devais le faire il y a quelques années lorsqu'un outil écrit en Lua utilisait le script Lua pour la config, puis ils nous ont demandé d'écrire un nouvel outil en C # et nous ont spécifiquement demandé d'utiliser le script de configuration Lua. Ils avaient un total de 2 lignes qui étaient réellement programmables et non simples x = y, mais je devais quand même en apprendre davantage sur les interprètes Lua open source pour .net à cause d’eux. Ce n'est pas un argument purement théorique.
Kevin Fee
21

Les autres réponses sont déjà très bonnes, je vais simplement apporter mon expérience d'utilisation dans le monde réel dans quelques projets.

Avantages

Ils sont pour la plupart déjà expliqués:

  • si vous êtes dans un programme Python, l'analyse est un jeu d'enfant ( eval); cela fonctionne automatiquement même pour des types de données plus complexes (dans notre programme, nous avons des points géométriques et des transformations, qui sont déchargés / chargés juste par repr/ eval);
  • créer une "fausse configuration" avec juste quelques lignes de code est trivial;
  • vous avez de meilleures structures et, à notre connaissance, une syntaxe bien meilleure que celle de JSON (même si je viens juste d'avoir des commentaires et de ne pas avoir à mettre des guillemets autour des clés de dictionnaire, vous gagnerez en lisibilité).

Les inconvénients

  • les utilisateurs malveillants peuvent faire tout ce que votre programme principal peut faire; Je ne considère pas cela comme un problème, car si un utilisateur peut modifier un fichier de configuration, il peut déjà faire ce que l’application peut faire;
  • si vous n'êtes plus dans un programme Python, vous avez maintenant un problème. Alors que plusieurs de nos fichiers de configuration sont restés confidentiels par rapport à leur application d'origine, un en particulier est venu stocker des informations utilisées par plusieurs programmes différents, dont la plupart sont actuellement en C ++, qui disposent maintenant d'un analyseur syntaxique piraté pour un petit fichier mal défini. sous-ensemble de Python repr. C'est évidemment une mauvaise chose.
  • Même si votre programme reste en Python, vous pouvez changer la version de Python. Disons que votre application a démarré en Python 2; après de nombreux tests, vous avez réussi à le migrer vers Python 3 - malheureusement, vous n'avez pas vraiment testé tout votre code - vous avez tous les fichiers de configuration qui traînent sur les machines de vos clients, écrites pour Python 2, et sur lesquelles pas vraiment le contrôle. Vous ne pouvez même pas fournir un "mode de compatibilité" pour lire les anciens fichiers de configuration (ce qui est souvent fait pour les formats de fichiers), à moins que vous ne souhaitiez regrouper / appeler l'interpréteur Python 2!
  • Même si vous êtes en Python, la modification du fichier de configuration à partir de code est un réel problème, car ... eh bien, la modification de code n'est pas du tout triviale, en particulier le code qui a une syntaxe riche et qui n'est pas dans LISP ou similaire. Un de nos programmes contient un fichier de configuration Python, écrit à la main à l’origine, mais il est apparu qu'il serait utile de manipuler le logiciel (un paramètre particulier est une liste de choses qu'il est beaucoup plus simple de réorganiser à l'aide d'une interface graphique). C'est un gros problème, parce que:

    • Même le simple fait d'effectuer une analyse → AST → réécrire l'aller-retour n'est pas anodin (vous remarquerez que la moitié des solutions proposées sont ensuite marquées comme "obsolètes, n'utilisent pas, ne fonctionnent pas dans tous les cas");
    • même s'ils travaillaient, AST est beaucoup trop bas; vous êtes généralement intéressé à manipuler le résultat des calculs effectués dans le fichier, pas les étapes qui y ont été effectuées;
    • Cela nous amène au simple fait que vous ne pouvez pas simplement éditer les valeurs qui vous intéressent, car elles peuvent être générées par des calculs complexes que vous ne pouvez pas comprendre / manipuler à travers votre code.

    Comparez cela avec JSON, INI ou XML (Dieu nous en préserve!), Où la représentation en mémoire peut toujours être modifiée et réécrite, sans perte de données (XML, où la plupart des analyseurs DOM peuvent conserver des espaces dans les nœuds de texte et de commentaire), ou perdez au moins un peu de formatage (JSON, où le format lui-même ne permet pas plus que les données brutes que vous lisez).


Donc, comme d'habitude, il n'y a pas de solution claire; Ma politique actuelle en la matière est la suivante:

  • si le fichier de configuration est:

    • sûrement pour une application Python et privée pour elle - comme dans, personne d’autre ne tentera jamais de la lire;
    • manuscrit;
    • venant d'une source de confiance;
    • L’utilisation de types de données d’application cible est vraiment une prime;

    un fichier Python peut être une idée valide;

  • si à la place:

    • il peut y avoir la possibilité d'avoir une autre application lue;
    • il est possible que ce fichier puisse être édité par une application, éventuellement même par mon application elle-même;
    • est fourni par une source non fiable.

    un format "données uniquement" peut être une meilleure idée.

Notez qu'il n'est pas nécessaire de faire un seul choix. J'ai récemment écrit une application qui utilise les deux approches. J'ai un fichier presque jamais modifié avec les paramètres de configuration initiale, manuscrits où il y a des avantages à avoir de beaux bonus Python, et un fichier JSON pour la configuration édité à partir de l'interface utilisateur.

Matteo Italia
la source
1
très bon point sur la génération ou la réécriture de config! Mais peu de formats autres que XML peuvent conserver des commentaires dans la sortie, ce que je considère extrêmement important pour la configuration. D'autres formats introduisent parfois un note:champ qui est ignoré pour la configuration.
amon
2
"si un utilisateur peut modifier un fichier de configuration, il / elle peut déjà faire ce que l'application peut faire" - ce n'est pas tout à fait vrai. Que diriez-vous de tester qu'un fichier de configuration brillant que quelqu'un que vous ne connaissez pas ait téléchargé sur pastebin?
Dmitry Grigoryev
2
@DmitryGrigoryev: si vous visez cette cible, vous pouvez également dire à votre victime de copier-coller curl ... | bash, c'est encore moins embêtant. :-P
Matteo Italia le
@DmitryGrigoryev: et c'est le genre de chose qui pourrait permettre à une personne de détruire complètement un système de production le premier jour de son travail. Si 'eval' est votre analyseur, cela signifie qu'il n'y a aucune possibilité de le vérifier avant la lecture. (la même raison pour laquelle les scripts shell sont si mauvais en production). INI, YAML ou JSON sont en sécurité à cet égard.
Joe
1
@DmitryGrigoryev: Mon point est juste que si votre type de victime est assez stupide pour copier-coller à l'aveuglette un fichier de configuration, vous pouvez probablement le tromper pour qu'il fasse ce qu'il veut sur sa machine avec des méthodes beaucoup moins obliques ("coller ceci dans une console"). corrigez votre problème! "). En outre, même avec des fichiers de configuration non exécutables, le risque de dommages est élevé: même si vous pointez malicieusement la journalisation sur des fichiers critiques (si l'application s'exécute avec suffisamment de privilèges), vous pouvez causer des dégâts considérables sur le système. C'est la raison pour laquelle je pense qu'en pratique, la sécurité n'est pas très différente.
Matteo Italia
8

La question principale est la suivante: voulez-vous que votre fichier de configuration soit dans un langage complet de Turing (comme Python)? Si vous le souhaitez, vous pouvez également envisager d'intégrer un autre langage de script (complet de Turing) tel que Guile ou Lua (car il pourrait être perçu comme "plus simple" à utiliser, ou à intégrer, que Python; lisez le chapitre sur Extension & Incorporation de Python ). Je ne discuterai pas de cela plus avant (car d'autres réponses, comme Amon par exemple , en ont discuté en profondeur), mais remarquez que l' intégration d'un langage de script dans votre application est un choix architectural majeur , à prendre très tôt en compte.; Je ne recommande vraiment pas de faire ce choix plus tard!

Un exemple bien connu de programme configurable via des "scripts" est l' éditeur GNU emacs (ou probablement AutoCAD dans le domaine propriétaire); Sachez donc que si vous acceptez les scripts, un utilisateur utilisera éventuellement - et peut-être même abusera, de votre point de vue - cette installation de manière intensive et créera un script de plusieurs milliers de lignes. par conséquent, le choix d'un langage de script suffisant est important.

Cependant (du moins sur les systèmes POSIX), il peut être utile d’activer le calcul dynamique du "fichier" de configuration au moment de l’initialisation (bien sûr, le fardeau d’une configuration rationnelle incombant à votre administrateur système ou à votre utilisateur; c’est en fait une configuration. texte qui provient d’un fichier ou d’une commande). Pour cela, vous pouvez simplement adopter la convention (et la documenter ) selon laquelle un chemin de fichier de configuration commençant par, par exemple, a !ou |est en fait une commande shell que vous liriez comme un pipeline . Cela laisse à l'utilisateur le choix d'utiliser le "préprocesseur" ou le "langage de script" avec lequel il est le plus familier.

(vous devez faire confiance à votre utilisateur pour les problèmes de sécurité si vous acceptez une configuration calculée dynamiquement)

Ainsi, dans votre code d’initialisation, vous mainaccepteriez (par exemple) des --config arguments confarg et en retirerions des argumentsFILE*configf; . Si cet argument commence par !(c'est-à-dire si (confarg[0]=='!')....), vous utiliseriez configf = popen(confarg+1, "r");et fermez ce tuyau avec pclose(configf);. Sinon, vous utiliseriez configf=fopen(confarg, "r");et fermeriez ce fichier avec fclose(configf);(n'oubliez pas la vérification des erreurs). Voir pipe (7) , popen (3) , fopen (3) . Pour une application codée en Python, lisez à propos de os.popen , etc ...

(document également pour l'utilisateur étrange qui souhaite passer un fichier de configuration nommé !foo.configà passer ./!foo.configpour contourner l' popenastuce ci-dessus)

En passant, une telle astuce n’est qu’une commodité (pour éviter d’obliger l’utilisateur avancé à coder par exemple un script shell pour générer un fichier de configuration ). Si l'utilisateur souhaite signaler un bogue, il doit vous envoyer le fichier de configuration généré ...

Notez que vous pouvez également concevoir votre application avec la possibilité d’utiliser et de charger des plugins au moment de l’initialisation, par exemple avec dlopen (3) (et vous devez faire confiance à votre utilisateur pour ce plugin). Là encore, il s’agit d’une décision très importante en matière d’architecture (et vous devez définir et fournir des API et des conventions relativement stables concernant ces plug-ins et votre application).

Pour une application codée dans un langage de script tel que Python, vous pouvez également accepter certains arguments de programme pour les primitives eval ou exec ou similaires. Encore une fois, les problèmes de sécurité sont alors la préoccupation de l'utilisateur (avancé) .

En ce qui concerne le format textuel pour votre fichier de configuration (que ce soit généré ou non), je crois que vous avez besoin surtout pour documenter bien (et le choix d' un certain format particulier est pas si important que cela, mais je vous recommande de laisser votre utilisateur soit en mesure de mettre quelques-uns commentaires commentés à l'intérieur). Vous pouvez utiliser JSON (de préférence avec un analyseur JSON acceptant et ignorant les commentaires avec les //lettres habituelles jusqu’à eol ou /*... */...), ou YAML, ou XML, ou INI ou votre propre chose. L'analyse d'un fichier de configuration est relativement facile (et vous trouverez de nombreuses bibliothèques liées à cette tâche).

Basile Starynkevitch
la source
+1 pour mentionner la complétude de Turing des langages de programmation. Certains travaux intéressants révèlent que la limitation de la puissance de calcul du format d'entrée est essentielle pour sécuriser la couche de traitement des entrées. L'utilisation d'un langage de programmation complet-Turing va dans le sens opposé.
Matheus Moreira
2

En ajoutant à la réponse d’ Amon , avez-vous envisagé des alternatives? JSON est peut-être plus que ce dont vous avez besoin, mais les fichiers Python vous poseront probablement des problèmes à l'avenir pour les raisons mentionnées ci-dessus.

Cependant, Python a déjà un analyseur de configuration pour un langage de configuration très simple qui pourrait répondre à tous vos besoins. Le ConfigParsermodule implémente un langage de configuration simple.

CodeMonkey
la source
1
Utiliser quelque chose de "semblable à ... fichiers Microsoft Windows INI" semble être une mauvaise idée, à la fois parce que ce n'est pas un format particulièrement flexible et parce que "similaire" implique des incompatibilités non documentées.
Pete Kirkham le
1
@PeteKirkham Eh bien, c'est simple, c'est documenté et cela fait partie de la bibliothèque standard Python. Cela pourrait être la solution idéale pour les besoins des OP, car il recherche quelque chose qui est directement pris en charge par Python et qui est plus simple que JSON. Tant qu'il ne précise pas quels sont ses besoins, je pense que cette réponse peut lui être utile.
CodeMonkey
1
J'allais suggérer essentiellement ceci: voir quels types de fichiers de configuration sont pris en charge par les bibliothèques Python et en choisir un. En outre, Powershell a la notion de sections de données - qui permettent des constructions de langage Powershell limitées - protégeant contre le code malveillant. Si Python a une bibliothèque qui prend en charge un sous-ensemble limité de Python pour la configuration, cela atténue au moins l'un des inconvénients par rapport à l'idée de l'OP.
pẘ
1
@PeteKirkham C'est plutôt un problème dans l'autre sens. Windows a tendance à avoir un tas de merde non documentée qui explose sur vous. Python a tendance à être bien documenté et simple. Cela dit, si vous avez simplement besoin de simples paires clé / valeur ( peut-être avec des sections), c'est un très bon choix. Je suppose que cela couvre 90% des cas d'utilisation. Si les fichiers de configuration de .NET étaient ini au lieu du XML monstrueux avec un schéma qui est en réalité un code se faisant passer pour config, nous serions tous beaucoup mieux lotis.
jpmc26
1
@PeteKirkham Pas vraiment. INI étant le meilleur choix pour les cas d’utilisation simples, il ya de fortes chances que vous puissiez éviter les incompatibilités. Ils n’ont également aucune importance si vous ne consommez pas le fichier dans deux langues différentes, et même si vous l’êtes, vous pouvez probablement trouver des implémentations ouvertes dans n’importe quelle langue (vous permettant ainsi de ne pas avoir d’incompatibilités ou, au minimum, de savoir exactement quoi. elles sont). Je conviens que vous devriez utiliser un autre format si votre cas d'utilisation est suffisamment complexe pour que vous commenciez à le rencontrer ou si vous ne pouvez pas trouver une implémentation existante fiable, mais ce n'est pas courant.
jpmc26
1

Je travaille depuis longtemps avec un logiciel bien connu dont les fichiers de configuration sont écrits en TCL. L'idée n'est donc pas nouvelle. Cela a très bien fonctionné, car les utilisateurs qui ne connaissaient pas la langue pouvaient toujours écrire / éditer des fichiers de configuration simples en utilisant une seule set name valueinstruction, tandis que les utilisateurs et les développeurs plus avancés pouvaient tirer des astuces sophistiquées avec cela.

Je ne pense pas que "les fichiers de configuration peuvent être difficiles à déboguer" est une préoccupation valable. Tant que votre application ne force pas les utilisateurs à écrire des scripts, ceux-ci peuvent toujours utiliser des affectations simples dans leurs fichiers de configuration, ce qui n'est guère plus difficile à obtenir que le JSON ou le XML.

La réécriture de la configuration est un problème, bien que ce ne soit pas aussi grave qu'il y paraît. La mise à jour de code arbitraire est impossible, mais le chargement de la configuration à partir d'un fichier, sa modification et sa sauvegarde le sont. Fondamentalement, si vous créez des scripts dans un fichier de configuration qui n'est pas en lecture seule, vous obtiendrez une liste d' set name valueinstructions équivalente une fois qu'il aura été enregistré. Un bon indice que cela se produira est un commentaire "ne pas modifier" au début du fichier.

Une chose à considérer est que vos fichiers de configuration ne seront pas lisibles de manière fiable par de simples outils basés sur regex, tels que sed, mais autant que je sache, ce n'est déjà pas le cas avec vos fichiers JSON actuels, il n'y a donc pas grand chose à perdre.

Assurez-vous simplement d’utiliser les techniques de sandbox appropriées lors de l’exécution de vos fichiers de configuration.

Dmitry Grigoryev
la source
1
« Logiciel » est un nom indénombrable, il devrait donc être « certains logiciels bien connus. »
jpmc26
1

Outre tous les points valables d'autres bonnes réponses ici (wow, ils ont même mentionné le concept de Turing-complete), il existe en fait deux ou trois bonnes raisons pratiques de ne PAS utiliser un fichier Python comme configuration, même lorsque vous travaillez sur un fichier Python. seul projet.

  1. Les paramètres d'un fichier source Python font techniquement partie d'un code source exécutable, plutôt que d'un fichier de données en lecture seule. Si vous choisissez cette voie, vous le ferez généralement import config, car ce genre de "commodité" était probablement l'une des principales raisons pour lesquelles les gens ont commencé par utiliser un fichier Python comme configuration au départ. Vous avez maintenant tendance à enregistrer ce fichier config.py dans votre référentiel, sinon l’utilisateur final rencontrerait un problème important ImportError lorsqu’il essaiera d’exécuter votre programme pour la première fois.

  2. En supposant que vous engagiez réellement ce fichier config.py dans votre référentiel, les membres de votre équipe auraient probablement des paramètres différents dans des environnements différents. Imaginez qu'un jour, un membre engage accidentellement son fichier de configuration local dans le référentiel.

  3. Dernier point mais non le moindre, votre projet pourrait avoir des mots de passe dans le fichier de configuration. (Il s'agit d'une pratique discutable en soi, mais elle se produit quand même.) Et si votre fichier de configuration existe dans le référentiel, vous risquez de valider vos informations d'identification dans un référentiel public.

Désormais, l’utilisation d’un fichier de configuration contenant uniquement des données, tel que le format JSON universel, peut éviter les 3 problèmes ci-dessus, car vous pouvez demander à l’utilisateur de créer son propre fichier config.json et de l’alimenter dans votre programme.

PS: Il est vrai que JSON a de nombreuses restrictions. Deux des limitations mentionnées par le PO peuvent être résolues par une certaine créativité.

RayLuo
la source