Quanto è cattiva l'idea usare i file Python come file di configurazione?


72

Ho sempre usato i file JSON per la configurazione delle mie applicazioni. Ho iniziato a usarli da quando ho codificato un sacco di Java, e ora sto lavorando principalmente allo sviluppo di Python lato server e data science e non sono sicuro che JSON sia la strada giusta da percorrere.

Ho visto il sedano utilizzare i file Python effettivi per la configurazione. Inizialmente ero scettico al riguardo. Ma l'idea di utilizzare semplici strutture di dati Python per la configurazione sta iniziando a crescere su di me. Alcuni professionisti:

  • Le strutture dei dati saranno le stesse di quelle che sto normalmente scrivendo. Quindi, non ho bisogno di cambiare idea.
  • Il mio IDE (PyCharm) comprende la connessione tra configurazione e codice. Ctrl+ Bconsente di saltare facilmente tra configurazione e codice.
  • Non ho bisogno di lavorare con JSON rigoroso inutile IMO . Ti guardo doppie virgolette, nessuna virgola finale e nessun commento.
  • Posso scrivere configurazioni di test nell'applicazione a cui sto lavorando, quindi trasferirle facilmente in un file di configurazione senza dover eseguire alcuna conversione e analisi JSON.
  • Se necessario, è possibile eseguire script molto semplici nel file di configurazione. (Anche se questo dovrebbe essere molto, molto limitato.)

Quindi, la mia domanda è: se cambio, come faccio a spararmi al piede?

Nessun utente finale non qualificato utilizzerà i file di configurazione. Qualsiasi modifica ai file di configurazione è attualmente impegnata in Git e viene implementata sui nostri server come parte della distribuzione continua. Non ci sono modifiche manuali alla configurazione, a meno che non ci sia un'emergenza o sia in fase di sviluppo.

(Ho considerato YAML , ma qualcosa mi irrita. Quindi, per ora è fuori dal tavolo americano.)


39
Non qualificato non è il tuo problema. È dannoso.
Blrfl,

9
Cosa intendi con "fuori dal tavolo americano" ?
Peter Mortensen,

24
"Quindi, per ora è fuori dal tavolo americano." === "Quindi per ora è, come dicono gli americani, fuori dal tavolo."
vescovo,

7
Se non ti piace JSON, dovresti provare yaml. Mi piace molto per le configurazioni. specialmente quando sono coinvolte stringhe più grandi, YAML è più leggibile di JSON.
Christian Sauer,

5
@bishop "off the table" in inglese britannico non significa più in considerazione, dal momento che le mozioni parlamentari vengono messe sul tavolo nel mezzo della Camera dei Comuni per riferimento quando vengono discusse, quindi anche "presentate per la discussione" (verbale parlamentare 1799 - books.google.co.uk/… ), AFAIK il significato statunitense è lo stesso, ma non so se hai un tavolo in parlamento.
Pete Kirkham,

Risposte:


92

L'utilizzo di un linguaggio di scripting al posto di un file di configurazione sembra a prima vista eccezionale: hai la piena potenza di quella lingua disponibile e puoi semplicemente eval()o no import. In pratica, ci sono alcuni gotcha:

  • è un linguaggio di programmazione, che deve essere appreso. Per modificare la configurazione, è necessario conoscere abbastanza bene questa lingua. I file di configurazione in genere hanno un formato più semplice che è più difficile sbagliare.

  • è un linguaggio di programmazione, il che significa che la configurazione può essere difficile da eseguire il debug. Con un normale file di configurazione lo guardi e vedi quali valori sono forniti per ogni proprietà. Con uno script, potenzialmente è necessario eseguirlo prima per vedere i valori.

  • è un linguaggio di programmazione, che rende difficile mantenere una chiara separazione tra la configurazione e il programma attuale. A volte vuoi questo tipo di estensibilità, ma a quel punto probabilmente stai piuttosto cercando un vero sistema di plugin.

  • è un linguaggio di programmazione, il che significa che la configurazione può fare tutto ciò che può fare il linguaggio di programmazione. Quindi, o stai usando una soluzione sandbox che nega gran parte della flessibilità del linguaggio, o stai ponendo grande fiducia nell'autore della configurazione.

Quindi usare uno script per la configurazione è probabilmente OK se il pubblico del tuo strumento è sviluppatori, ad esempio Sphinx config o setup.py nei progetti Python. Altri programmi con configurazione eseguibile sono shell come Bash e editor come Vim.

L'uso di un linguaggio di programmazione per la configurazione è necessario se la configurazione contiene molte sezioni condizionali o se fornisce callback / plug-in. L'uso diretto di uno script invece di eval () - alcuni campi di configurazione tendono ad essere più debuggabili (si pensi alle tracce dello stack e ai numeri di riga!).

L'uso diretto di un linguaggio di programmazione può anche essere una buona idea se la tua configurazione è così ripetitiva che stai scrivendo script per generare automaticamente la configurazione. Ma forse un modello di dati migliore per la configurazione potrebbe rimuovere la necessità di una tale configurazione esplicita? Ad esempio, può essere utile se il file di configurazione può contenere segnaposto che verranno successivamente espansi. Un'altra caratteristica a volte vista è la presenza di più file di configurazione con precedenza diversa che possono sovrascrivere a vicenda, sebbene ciò presenti alcuni problemi propri.

Nella maggior parte dei casi, i file INI, i file delle proprietà Java o i documenti YAML sono molto più adatti alla configurazione. Per modelli di dati complessi, può essere applicabile anche XML. Come hai notato, JSON ha alcuni aspetti che lo rendono inadatto come file di configurazione modificabile dall'uomo, sebbene si tratti di un formato di scambio dati accurato.


25
Esistono un paio di formati di file di configurazione "accidentalmente Turing-complete", il più famoso sendmail.cf. Ciò indicherebbe che l'uso di un vero linguaggio di scripting potrebbe essere utile, dal momento che quello è stato effettivamente progettato per essere completo di Turing. Tuttavia , Turing-completezza e "Tetris-completezza" sono due cose diverse, e mentre sendmail.cfpuò calcolare funzioni arbitrarie, può non inviare il vostro /etc/passwdsopra la rete o formattare il vostro hard disk, che Python o Perl sarebbe in grado di.
Jörg W Mittag,

3
@ JörgWMittag Torino-completezza non implica essere in grado di inviare cose sulla rete o accedere al disco rigido. Cioè, la completezza di Torino riguarda l'elaborazione non sull'I / O. Ad esempio, CSS è considerato Torino completo, ma non rovinerà la tua memoria permanente. Hai detto altrove che "Idris è un linguaggio funzionale totalmente puro, quindi per definizione non è completo di Turing", che non segue, e apparentemente è Torino completa. Ero convinto che il tuo uso di Testris-complete significasse che la lingua era Torino completa ma non era in grado di eseguire l'I / O completo ... sembra che non sia quello che intendi.
Theraot,

6
@Theraot: "Totale" significa che ritorna sempre. Una macchina di Turing può eseguire un ciclo infinito, cioè ha la capacità di non tornare. Ergo, Idris non può fare tutto ciò che fa una Macchina di Turing, il che significa che non è completa di Turing. Questo vale per tutte le lingue tipizzate in modo dipendente. Il punto centrale di un linguaggio tipicamente dipendente è che puoi decidere proprietà arbitrarie sui programmi, mentre in un linguaggio completo di Turing non puoi nemmeno decidere proprietà banali come "questo programma si ferma?" Le lingue totali non sono per definizione complete di Turing, poiché le macchine di Turing sono parziali.
Jörg W Mittag,

10
La definizione di "Turing-complete" è "può implementare una macchina di Turing". La definizione di "Tetris-complete" è "può implementare Tetris". Il punto centrale di questa definizione è che la completezza di Turing non è semplicemente molto interessante nel mondo reale. Esistono molti linguaggi utili che non sono completi di Turing, ad esempio HTML, SQL (pre-1999), vari DSL, ecc. OTOH, la completezza di Turing implica solo che è possibile calcolare le funzioni su numeri naturali, non implica stampare sullo schermo, accedere alla rete, interagire con l'utente, il sistema operativo, l'ambiente, tutti elementi importanti.
Jörg W Mittag,

4
Il motivo per cui Edwin Brady ha usato questo esempio è perché molte persone pensano che le lingue che non sono complete di Turing non possano essere utilizzate per la programmazione generale. Anch'io pensavo che anche questo, dal momento che molti programmi interessanti sono essenzialmente cicli infiniti che non vogliamo fermare , ad esempio server, sistemi operativi, loop di eventi in una GUI, loop di gioco. Molti programmi elaborano infiniti dati, ad es. Flussi di eventi. Pensavo che non potessi scriverlo in una lingua totale, ma da allora ho imparato che puoi , e quindi trovo una buona idea avere un termine per quella capacità.
Jörg W Mittag,

50

+1 a tutto nella risposta di Amon . Vorrei aggiungere questo:

Ti pentirai di aver usato il codice Python come linguaggio di configurazione la prima volta che desideri importare la stessa configurazione da un codice scritto in una lingua diversa. Ad esempio, se il codice che fa parte del tuo progetto ed è scritto in C ++ o Ruby o qualcos'altro deve inserire la configurazione, dovrai collegare l'interprete Python come libreria o analizzare la configurazione in un coprocesso Python, entrambi che sono imbarazzanti, difficili o dall'alto.

Tutto il codice che importa questa configurazione oggi può essere scritto in Python, e potresti pensare che questo sia vero anche domani, ma lo sai per certo?

Hai detto che avresti usato la logica (qualsiasi altra cosa che le strutture di dati statiche) nella tua configurazione con parsimonia, se non del tutto, il che è buono, ma se c'è qualcosa del genere, ti sarà difficile in futuro annullarlo in modo da può tornare a un file di configurazione dichiarativo.

EDIT per la cronaca: diverse persone hanno commentato questa risposta su quanto sia probabile o improbabile che un progetto venga mai completamente riscritto con successo in un'altra lingua. È giusto dire che una riscrittura completa compatibile con le versioni precedenti è probabilmente vista raramente. Quello che avevo in mente era che parti dello stesso progetto (e che necessitavano di accedere alla stessa configurazione) venivano scritte in lingue diverse. Ad esempio, servendo lo stack in C ++ per la velocità, la pulizia batch del database in Python, alcuni script di shell come colla. Quindi spendi un pensiero anche per quel caso :)


1
@Mast, mi scuso, ma non seguo. Il nome del file (anche se termina in .py) non è né qui né lì. Il punto che sto cercando di sottolineare è che se è scritto in Python allora hai bisogno di un interprete Python per leggerlo.
Celada,

12
@Mast Penso che stai analizzando nel modo sbagliato. Il punto che ho preso da questa risposta (sia originale che modificata) è che la scelta di scrivere file di configurazione in un linguaggio di programmazione è che rende più difficile scrivere codice in un'altra lingua. Ad esempio, decidi di trasferire la tua app su Anrdoid / iPhone e utilizzerai un'altra lingua. Devi (a) fare affidamento su un interprete Python sull'app del telefono cellulare (non ideale), (b) riscrivere la configurazione in un formato indipendente dalla lingua e riscrivere il codice Python che l'ha usato, oppure (c) mantenere due formati di configurazione in futuro.
Jon Bentley,

4
@JonBentley Suppongo che la preoccupazione sarà rilevante se ci sono piani per fare progetti multilingue. Non ho avuto quell'impressione dall'OP. Inoltre, l'utilizzo di file di testo per la configurazione richiede ancora codice aggiuntivo (in tutte le lingue) per l'analisi / conversione effettiva dei valori. Tecnicamente, se limitano il lato Python alle key=valueassegnazioni per la configurazione, non vedo perché un programma Java / C ++ non sia in grado di leggere il file Python come un semplice file di testo e analizzarlo allo stesso modo se devono spostarsi in qualcos'altro in il futuro. Non vedo la necessità di un vero interprete Python.
code_dredd,

3
@ray True, ma la risposta è ancora utile sulla base del fatto che le domande non dovrebbero essere applicabili solo alla persona che le pubblica. Se si utilizza un formato standardizzato (ad esempio INI, JSON, YAML, XML, ecc.), Probabilmente si utilizzerà una libreria di analisi esistente anziché scriverne una propria. Ciò riduce il lavoro aggiuntivo a una sola classe adattatore per l'interfaccia con la libreria di analisi. Se ti stai limitando a key = value, allora questo elimina la maggior parte dei motivi dell'OP per utilizzare Python in primo luogo e potresti anche scegliere un formato riconosciuto.
Jon Bentley,

3
Ho dovuto farlo qualche anno fa quando uno strumento scritto in Lua usava lo script Lua come sua configurazione, quindi volevano che scrivessimo un nuovo strumento in C # e ci hanno chiesto specificamente di usare lo script di configurazione Lua. Avevano un totale di 2 righe che erano effettivamente programmabili e non semplici x = y, ma ho dovuto imparare a conoscere gli interpreti Lua open source per .net a causa loro. Non è un argomento puramente teorico.
Kevin Fee,

21

Le altre risposte sono già molto buone, porterò la mia esperienza di utilizzo nel mondo reale in alcuni progetti.

Professionisti

Sono per lo più già esplicitati:

  • se ti trovi in ​​un programma Python, l'analisi è un gioco da ragazzi ( eval); funziona automaticamente anche per tipi di dati più complessi (nel nostro programma, abbiamo punti geometrici e trasformazioni, che vengono scaricati / caricati bene attraverso repr/ eval);
  • la creazione di una "configurazione falsa" con poche righe di codice è banale;
  • hai strutture migliori e, IMO, una sintassi decisamente migliore di JSON (jeez anche solo avere commenti e non dover mettere virgolette doppie attorno alle chiavi del dizionario è una grande vittoria di leggibilità).

Contro

  • gli utenti malintenzionati possono fare tutto ciò che il tuo programma principale può fare; Non considero questo un problema, dal momento che generalmente se un utente può modificare un file di configurazione, può già fare qualunque cosa l'applicazione possa fare;
  • se non sei più in un programma Python, ora hai un problema. Mentre molti dei nostri file di configurazione sono rimasti privati ​​della loro applicazione originale, uno in particolare è arrivato alla memorizzazione di informazioni utilizzate da diversi programmi, la maggior parte dei quali sono attualmente in C ++, che ora hanno un parser hackerato per un piccolo mal definito sottoinsieme di Python repr. Questa è ovviamente una brutta cosa.
  • Anche se il tuo programma rimane in Python, puoi cambiare la versione di Python. Supponiamo che l'applicazione sia stata avviata in Python 2; dopo molti test sei riuscito a migrarlo su Python 3 - sfortunatamente, non hai davvero testato tutto il tuo codice - hai tutti i file di configurazione in giro sui computer dei tuoi clienti, scritti per Python 2 e su cui doni davvero avere il controllo. Non è nemmeno possibile fornire una "modalità di compatibilità" per leggere i vecchi file di configurazione (cosa che spesso viene fatta per i formati di file), a meno che non si sia disposti a raggruppare / chiamare l'interprete Python 2!
  • Anche se sei in Python, la modifica del file di configurazione dal codice è un vero problema, perché ... beh, la modifica del codice non è affatto banale, in particolare il codice che ha una sintassi ricca e non è in LISP o simile. Un nostro programma ha un file di configurazione che è Python, originariamente scritto a mano, ma che in seguito si è rivelato utile per manipolare via software (una particolare impostazione è un elenco di cose che è molto più semplice riordinare usando una GUI). Questo è un grosso problema, perché:

    • anche solo eseguire un analisi → AST → riscrivere andata e ritorno non è banale (noterai che metà delle soluzioni proposte sono in seguito contrassegnate come "obsolete, non usare, non funzionano in tutti i casi");
    • anche se hanno funzionato, AST è di livello troppo basso; sei generalmente interessato a manipolare il risultato dei calcoli eseguiti nel file, non i passaggi che lo hanno portato;
    • che ci porta al semplice fatto che non puoi semplicemente modificare i valori che ti interessano, perché potrebbero essere generati da un calcolo complesso che non puoi capire / manipolare attraverso il tuo codice.

    Confronta questo con JSON, INI o (God forbid!) XML, dove la rappresentazione in memoria può sempre essere modificata e riscritta senza perdita di dati (XML, dove la maggior parte dei parser DOM può mantenere spazi bianchi nei nodi di testo e nei nodi di commento) o almeno perdendo solo un po 'di formattazione (JSON, dove il formato stesso non consente molto di più dei dati grezzi che stai leggendo).


Quindi, come al solito, non esiste una soluzione chiara; la mia attuale politica in materia è:

  • se il file di configurazione è:

    • sicuramente per un'applicazione Python e privata ad essa - come in, nessun altro proverà mai a leggere da essa;
    • scritta a mano;
    • proveniente da una fonte attendibile;
    • l'utilizzo dei tipi di dati delle applicazioni target è davvero un premio;

    un file Python può essere un'idea valida;

  • se invece:

    • potrebbe esserci la possibilità di leggere qualche altra applicazione da essa;
    • esiste la possibilità che questo file possa essere modificato da un'applicazione, possibilmente anche dalla mia stessa applicazione;
    • è fornito da una fonte non attendibile.

    un formato "solo dati" potrebbe essere un'idea migliore.

Si noti che non è necessario effettuare un'unica scelta: di recente ho scritto un'applicazione che utilizza entrambi gli approcci. Ho un file quasi mai modificato con impostazioni scritte a mano di prima installazione in cui vi sono vantaggi di avere dei bei bonus Python e un file JSON per la configurazione modificato dall'interfaccia utente.


1
ottimo punto su come generare o riscrivere la configurazione! Ma pochi formati diversi da XML possono conservare commenti nell'output, che considero estremamente importanti per la configurazione. Altri formati a volte introducono un note:campo che viene ignorato per la configurazione.
amon,

2
"se un utente può modificare un file di configurazione, può già fare tutto ciò che l'applicazione può fare" - questo non è del tutto vero. Che ne dici di testare il file di configurazione lucido che qualcuno che non conosci ha caricato su pastebin?
Dmitry Grigoryev,

2
@DmitryGrigoryev: se stai mirando a quel bersaglio potresti anche dire alla tua vittima di copiare e incollare un po ' curl ... | bash, è ancora meno una seccatura. :-P
Matteo Italia,

@DmitryGrigoryev: ed è il tipo di cosa che potrebbe consentire a qualcuno di distruggere completamente un sistema di produzione il primo giorno di lavoro. Se 'eval' è il tuo parser, ciò significa che non c'è alcuna possibilità di verificarlo prima che venga letto. (lo stesso motivo per cui gli script di shell sono così male nella produzione). INI, YAML o JSON sono al sicuro in questo senso.
Joe,

1
@DmitryGrigoryev: il mio punto è che se il tuo tipo di vittima è abbastanza stupido da copiare e incollare ciecamente un file di configurazione, probabilmente puoi indurlo a fare qualsiasi cosa sulla loro macchina con metodi meno obliqui ("incollalo in una console per risolvi il tuo problema! "). Inoltre, anche con file di configurazione non eseguibili c'è molto potenziale di danno - anche solo puntando maliziosamente la registrazione su file critici (se l'applicazione viene eseguita con privilegi sufficienti) puoi rovinare il sistema. Questo è il motivo per cui penso che in pratica non ci sia molta differenza in termini di sicurezza.
Matteo Italia,

8

La domanda principale è: vuoi che il tuo file di configurazione sia in un linguaggio completo di Turing (come lo è Python)? Se lo desideri, potresti anche prendere in considerazione l'idea di incorporare un altro linguaggio di scripting (Turing completo) come Guile o Lua (perché potrebbe essere percepito come "più semplice" da usare o da incorporare rispetto a Python; leggi il capitolo su Estensione e & Incorporamento di Python ). Non ne discuterò ulteriormente (perché altre risposte - di Amon - ne hanno discusso in profondità), ma noto che incorporare un linguaggio di scripting nella tua applicazione è una scelta architettonica importante , che dovresti considerare molto presto; Non raccomando davvero di fare questa scelta in seguito!

Un esempio ben noto di un programma configurabile tramite "script" è l' editor di emacs GNU (o probabilmente AutoCAD nel regno proprietario); quindi tieni presente che se accetti lo scripting, qualche utente alla fine userebbe, e forse abuserà, dal tuo punto di vista, tale funzionalità ampiamente e creerebbe uno script con più di mille righe; quindi la scelta di un linguaggio di scripting abbastanza buono è importante.

Tuttavia (almeno su sistemi POSIX), si potrebbe considerare conveniente per consentire il "file" di configurazione per essere dinamicamente calcolato in fase di inizializzazione (naturalmente, lasciando l'onere di una configurazione sano al vostro amministratore di sistema o l'utente; in realtà si tratta di una configurazione testo che proviene da un file o da un comando). Per questo, potresti semplicemente adottare la convenzione (e documentarla ) che un percorso del file di configurazione che inizia con es. A !o a |è in realtà un comando di shell che dovresti leggere come pipeline . Ciò lascia all'utente la scelta di utilizzare qualsiasi "preprocessore" o "linguaggio di scripting" con cui ha più familiarità.

(devi fidarti del tuo utente riguardo ai problemi di sicurezza se accetti una configurazione calcolata dinamicamente)

Quindi, nel tuo codice di inizializzazione, mainaccetteresti (ad esempio) un --config argomento confarg e ne ricaveresti un po FILE*configf;'. Se quell'argomento inizia con !(cioè se (confarg[0]=='!')....), useresti configf = popen(confarg+1, "r");e chiuderesti quella pipe con pclose(configf);. Altrimenti dovresti usare configf=fopen(confarg, "r");e chiudere quel file con fclose(configf);(non dimenticare il controllo degli errori). Vedi pipe (7) , popen (3) , fopen (3) . Per un'applicazione codificata in Python leggi di os.popen , ecc ...

(documento anche per l'utente strano che desidera passare un file di configurazione chiamato !foo.configper passare ./!foo.configper aggirare il popentrucco sopra)

A proposito, un simile trucco è solo una comodità (per evitare che l'utente avanzato debba, ad esempio, codificare alcuni script di shell per generare un file di configurazione ). Se l'utente desidera segnalare un bug, deve inviarti il file di configurazione generato ...

Nota che potresti anche progettare la tua applicazione con la possibilità di usare e caricare plugin al momento dell'inizializzazione, ad esempio con dlopen (3) (e devi fidarti del tuo utente su quel plugin). Ancora una volta, questa è una decisione architetturale molto importante (e devi definire e fornire alcune API e convenzioni piuttosto stabili su questi plugin e la tua applicazione).

Per un'applicazione codificata in un linguaggio di scripting come Python potresti anche accettare alcuni argomenti del programma per eval o exec o primitive simili. Ancora una volta, i problemi di sicurezza sono quindi la preoccupazione dell'utente (avanzato) .

Per quanto riguarda il formato testuale per il tuo file di configurazione (sia esso generato o meno), credo che devi principalmente documentarlo bene (e la scelta di un determinato formato non è così importante; tuttavia ti consiglio di lasciare che il tuo utente sia in grado di mettere alcuni commenti -skipping- al suo interno). Puoi usare JSON (preferibilmente con un parser JSON che accetta e salta i commenti con la solita //fino a eol o /*... */...), o YAML, o XML, o INI o le tue cose. L'analisi di un file di configurazione è ragionevolmente semplice (e troverai molte librerie relative a quell'attività).


+1 per menzionare la completezza di Turing dei linguaggi di programmazione. Alcuni lavori interessanti rivelano che limitare la potenza computazionale del formato di input è la chiave per proteggere il livello di gestione dell'input. L'uso di un linguaggio di programmazione completo di Turing va nella direzione opposta.
Matheus Moreira,

2

Aggiungendo alla risposta di Amon , hai considerato alternative? JSON è forse più del necessario, ma i file Python probabilmente ti daranno problemi in futuro per i motivi sopra menzionati.

Tuttavia Python ha già un parser di configurazione per un linguaggio di configurazione molto semplice che potrebbe soddisfare tutte le tue esigenze. Il ConfigParsermodulo implementa un linguaggio di configurazione semplice.


1
Usare qualcosa di "simile a ... file INI di Microsoft Windows" sembra essere una cattiva idea, sia per il fatto che non è un formato particolarmente flessibile, sia perché "simile" implica incompatibilità non documentate.
Pete Kirkham,

1
@PeteKirkham Bene, è semplice, è documentato e fa parte della libreria standard di Python. Potrebbe essere la soluzione perfetta per le esigenze dei PO, perché sta cercando qualcosa che è supportato direttamente da Python ed è più semplice di JSON. Fintanto che non specifica ulteriormente quali sono le sue esigenze, penso che questa risposta possa essere utile per lui.
CodeMonkey,

1
Stavo per suggerire essenzialmente questo: vedere quali tipi di file di configurazione supportano le librerie Python e sceglierne uno. Inoltre, Powershell ha la nozione di sezioni di dati - che consentono costrutti di linguaggio Powershell limitati - protezione da codice dannoso. Se Python ha una lib che supporta un sottoinsieme limitato di Python per la configurazione, questo almeno mitiga uno dei contro rispetto all'idea nell'OP.
ẘpẘ

1
@PeteKirkham È più probabile che sia un problema al contrario. Windows tende ad avere un sacco di merda senza documenti che esplode su di te. Python tende ad essere ben documentato e semplice. Detto questo, se tutto ciò di cui hai bisogno sono semplici coppie chiave / valore ( forse con sezioni), è una buona scelta. Sospetto che questo copra il 90% dei casi d'uso. Se i file di configurazione di .NET fossero ini invece del mostruoso XML con uno schema che in realtà è il codice mascherato da config, saremmo tutti molto meglio.
jpmc26,

1
@PeteKirkham Non proprio. INI è il migliore per i semplici casi di utilizzo, in primo luogo, è probabile che tu possa evitare eventuali incompatibilità. Inoltre, non importa se non stai consumando il file con due lingue diverse e, anche se lo sei, puoi probabilmente trovare implementazioni aperte in qualsiasi lingua (permettendoti di non avere incompatibilità o, almeno, sapere esattamente cosa loro sono). Sono d'accordo che dovresti usare un altro formato se il tuo caso d'uso è in realtà abbastanza complesso da iniziare a eseguirli o se non riesci a trovare un'implementazione esistente di cui ti puoi fidare, ma non è comune.
jpmc26,

1

Ho lavorato a lungo con alcuni software ben noti che hanno i suoi file di configurazione scritti in TCL, quindi l'idea non è nuova. Questo ha funzionato abbastanza bene, dal momento che gli utenti che non conoscevano la lingua potevano ancora scrivere / modificare semplici file di configurazione usando una singola set name valueistruzione, mentre utenti e sviluppatori più avanzati potevano trarne sofisticati trucchi.

Non penso che "i file di configurazione possano diventare difficili da eseguire il debug" è una preoccupazione valida. Finché l'applicazione non impone agli utenti di scrivere script, gli utenti possono sempre utilizzare semplici assegnazioni nei loro file di configurazione, il che non è più difficile da ottenere rispetto a JSON o XML.

Riscrivere la configurazione è un problema, anche se non è così grave come sembra. L'aggiornamento di codice arbitrario è impossibile, ma lo è il caricamento della configurazione da un file, la sua modifica e il suo salvataggio. Fondamentalmente, se esegui alcuni script in un file di configurazione che non è di sola lettura, finirai con un elenco equivalente di set name valueistruzioni una volta salvato. Un buon suggerimento che ciò accadrà è un commento "non modificare" all'inizio del file.

Una cosa da considerare è che i tuoi file di configurazione non saranno leggibili in modo affidabile da semplici strumenti basati su regex, come sed, ma per quanto ho capito questo non è già il caso dei tuoi attuali file JSON, quindi non c'è molto da perdere.

Assicurati solo di usare le appropriate tecniche di sandboxing quando esegui i tuoi file di configurazione.


1
"Software" è un sostantivo non numerabile, quindi dovrebbe essere " un software ben noto".
jpmc26,

1

Oltre a tutti i punti validi di altre buone risposte qui (wow, hanno persino menzionato il concetto completo di Turing), ci sono in realtà un paio di solidi motivi pratici per NON usare un file Python come configurazione, anche quando stai lavorando su un Python- solo progetto.

  1. Le impostazioni all'interno di un file sorgente Python sono tecnicamente parte del codice sorgente eseguibile, piuttosto che un file di dati di sola lettura. Se segui questa strada, in genere lo faresti import config, perché quel tipo di "convenienza" era presumibilmente uno dei motivi principali per cui le persone hanno iniziato a utilizzare un file Python come configurazione in primo luogo. Ora si tende a impegnare quel config.py nel repository, altrimenti l'utente finale incontrerebbe un ImportError confuso quando tentano di eseguire il programma per la prima volta.

  2. Supponendo che tu abbia effettivamente impegnato quella config.py nel tuo repository, ora i membri del tuo team avrebbero probabilmente impostazioni diverse su un ambiente diverso. Immagina che un giorno in qualche modo un membro commetta accidentalmente il suo file di configurazione locale nel repository.

  3. Ultimo ma non meno importante, il tuo progetto potrebbe contenere password nel file di configurazione. (Questa è una pratica discutibile a sé stante, ma succede comunque.) E se il tuo file di configurazione esiste in repository, rischi di trasferire le tue credenziali in un repository pubblico.

Ora, usando un file di configurazione solo dati, come il formato JSON universale, puoi evitare tutti e 3 i problemi sopra, perché puoi ragionevolmente chiedere all'utente di inventare il proprio config.json e inserirlo nel tuo programma.

PS: È vero che JSON ha molte restrizioni. 2 delle limitazioni menzionate dal PO, possono essere risolte con un po 'di creatività.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.