¿Qué tan mala idea es usar archivos Python como archivos de configuración?

72

Siempre he usado archivos JSON para la configuración de mis aplicaciones. Comencé a usarlos desde que codifiqué mucho Java, y ahora estoy trabajando principalmente en el desarrollo de Python del lado del servidor y de la ciencia de datos y no estoy seguro de si JSON es el camino correcto.

He visto a Celery usar archivos reales de Python para la configuración. Inicialmente era escéptico al respecto. Pero la idea de usar estructuras de datos Python simples para la configuración está comenzando a crecer en mí. Algunos pros:

  • Las estructuras de datos serán las mismas que normalmente estoy codificando. Por lo tanto, no necesito cambiar el estado de ánimo.
  • Mi IDE (PyCharm) comprende la conexión entre la configuración y el código. Ctrl+ Bpermite saltar fácilmente entre la configuración y el código.
  • No necesito trabajar con IMO innecesaria estricta JSON . Estoy viendo comillas dobles, sin comas y sin comentarios.
  • Puedo escribir configuraciones de prueba en la aplicación en la que estoy trabajando, luego transferirlas fácilmente a un archivo de configuración sin tener que hacer ninguna conversión y análisis JSON.
  • Es posible hacer scripts muy simples en el archivo de configuración si es realmente necesario. (Aunque esto debería ser muy, muy limitado).

Entonces, mi pregunta es: si cambio, ¿cómo me estoy disparando en el pie?

Ningún usuario final no calificado utilizará los archivos de configuración. Cualquier cambio en los archivos de configuración está actualmente comprometido con Git y se implementa en nuestros servidores como parte de la implementación continua. No hay cambios de configuración manuales, a menos que haya una emergencia o esté en desarrollo.

(He considerado YAML , pero algo me molesta. Entonces, por ahora está fuera de la mesa estadounidense).

André Christoffer Andersen
fuente
39
No calificado no es tu problema. Malicioso es.
Blrfl
9
¿Qué quieres decir con "fuera de la mesa americana" ?
Peter Mortensen
24
"Entonces, por ahora está fuera de la mesa estadounidense". === "Así que por ahora está, como dicen los estadounidenses, fuera de la mesa".
obispo
77
Si no te gusta JSON, deberías probar yaml. Me gusta mucho para las configuraciones. especialmente cuando se trata de cadenas más grandes, YAML es mucho más legible que JSON.
Christian Sauer
55
@bishop "fuera de la mesa" en inglés del Reino Unido significa que ya no se toma en consideración, ya que las mociones parlamentarias se ponen sobre la mesa en el centro de la Cámara de los Comunes para referencia cuando se discute, por lo tanto, también se 'presentan para discusión' (registro parlamentario 1799 - books.google.co.uk/… ), AFAIK el significado de EE. UU. es el mismo, pero no sé si tiene una mesa en su parlamento.
Pete Kirkham

Respuestas:

92

El uso de un lenguaje de script en lugar de un gran archivo de configuración parece a primera vista: usted tiene todo el poder de ese idioma disponible y sólo se puede eval()o importella. En la práctica, hay algunas trampas:

  • Es un lenguaje de programación que necesita ser aprendido. Para editar la configuración, debe conocer este idioma lo suficientemente bien. Los archivos de configuración suelen tener un formato más simple que es más difícil de equivocar.

  • Es un lenguaje de programación, lo que significa que la configuración puede ser difícil de depurar. Con un archivo de configuración normal, lo mira y ve qué valores se proporcionan para cada propiedad. Con un script, posiblemente necesite ejecutarlo primero para ver los valores.

  • Es un lenguaje de programación, lo que hace difícil mantener una separación clara entre la configuración y el programa real. A veces quieres este tipo de extensibilidad, pero en ese momento probablemente estés buscando un sistema de plugins real.

  • es un lenguaje de programación, lo que significa que la configuración puede hacer cualquier cosa que el lenguaje de programación pueda hacer. Entonces, o está utilizando una solución de sandbox que niega gran parte de la flexibilidad del lenguaje, o está depositando una gran confianza en el autor de la configuración.

Por lo tanto, es probable que usar un script para la configuración esté bien si la audiencia de su herramienta son desarrolladores, por ejemplo, Sphinx config o setup.py en proyectos de Python. Otros programas con configuración ejecutable son shells como Bash y editores como Vim.

Es necesario usar un lenguaje de programación para la configuración si la configuración contiene muchas secciones condicionales, o si proporciona devoluciones de llamada / complementos. Usar un script directamente en lugar de eval (): algunos campos de configuración tienden a ser más depurables (¡piense en los seguimientos de pila y los números de línea!).

El uso directo de un lenguaje de programación también puede ser una buena idea si su configuración es tan repetitiva que está escribiendo scripts para autogenerar la configuración. ¿Pero quizás un mejor modelo de datos para la configuración podría eliminar la necesidad de una configuración tan explícita? Por ejemplo, puede ser útil si el archivo de configuración puede contener marcadores de posición que luego expandirá. Otra característica que se ve a veces es que varios archivos de configuración tienen una precedencia diferente que pueden anularse entre sí, aunque eso presenta algunos problemas propios.

En la mayoría de los casos, los archivos INI, los archivos de propiedades Java o los documentos YAML son mucho más adecuados para la configuración. Para modelos de datos complejos, XML también puede ser aplicable. Como ha notado, JSON tiene algunos aspectos que lo hacen inadecuado como un archivo de configuración editable por humanos, aunque es un excelente formato de intercambio de datos.

amon
fuente
25
Hay un par de formatos de archivo de configuración que son "accidentalmente completados por Turing", el más famoso sendmail.cf. Eso indicaría que usar un lenguaje de script real podría ser beneficioso, ya que ese fue diseñado para ser Turing completo. Sin embargo , Turing-completo y "Tetris-completitud" son dos cosas diferentes, y si bien sendmail.cfpuede calcular funciones arbitrarias, que pueden no enviar su /etc/passwdsobre la red o formatear el disco duro, lo que Python o Perl sería capaz de hacerlo.
Jörg W Mittag
3
@ JörgWMittag Turin-completness no implica poder enviar cosas a través de la red o acceder al disco duro. Es decir, la completitud de Turín se trata de procesar, no de E / S. Por ejemplo, CSS se considera completo en Turín, pero no interferirá con su almacenamiento permanente. Usted ha dicho en otra parte que "Idris es un lenguaje funcional totalmente puro, por lo que, por definición, no es completo de Turing", eso no sigue, y aparentemente es Turín completo. Estaba convencido de que su uso de Testris-complete significaba que el idioma era completo en Turín pero no podía hacer E / S completas ... parece que eso no es lo que quiere decir.
Theraot
66
@Theraot: "Total" significa que siempre regresa. Una máquina de Turing puede realizar un bucle infinito, es decir, tiene la capacidad de no volver. Ergo, Idris no puede hacer todo lo que hace una máquina de Turing, lo que significa que no está completa. Esto es cierto para todos los idiomas de tipo dependiente. El objetivo de un lenguaje de tipo dependiente es que puede decidir propiedades arbitrarias sobre los programas, mientras que en un lenguaje completo de Turing ni siquiera puede decidir propiedades triviales como "¿se detiene este programa?" Los lenguajes totales son, por definición, no completos de Turing, porque las máquinas de Turing son parciales.
Jörg W Mittag
10
La definición de "Turing-complete" es "puede implementar una máquina de Turing". La definición de "Tetris-complete" es "puede implementar Tetris". El objetivo de esta definición es que la integridad de Turing simplemente no es muy interesante en el mundo real. Hay muchos lenguajes útiles que no son completos para Turing, por ejemplo, HTML, SQL (anterior a 1999), varios DSL, etc. imprimir en la pantalla, acceder a la red, interactuar con el usuario, el sistema operativo, el entorno, todo lo cual es importante.
Jörg W Mittag
44
La razón por la cual Edwin Brady usó este ejemplo es porque muchas personas piensan que los lenguajes que no son completos para Turing no pueden usarse para programación de propósito general. Yo también solía pensar que, dado que, después de todo, muchos programas interesantes son esencialmente bucles infinitos que no queremos detener , por ejemplo, servidores, sistemas operativos, bucles de eventos en una GUI, bucles de juegos. Muchos programas procesan datos infinitos, por ejemplo, secuencias de eventos. Solía ​​pensar que no se puede escribir eso en un idioma total, pero desde entonces aprendí que sí se puede , por lo que me parece una buena idea tener un término para esa capacidad.
Jörg W Mittag
50

+1 a todo en la respuesta de amon . Me gustaría agregar esto:

Lamentará usar el código Python como su idioma de configuración la primera vez que quiera importar la misma configuración desde dentro del código escrito en un idioma diferente. Por ejemplo, si el código que forma parte de su proyecto y está escrito en C ++ o Ruby o algo más necesita incorporar la configuración, deberá vincular el intérprete de Python como una biblioteca o analizar la configuración en un coproceso de Python, ambos que son incómodos, difíciles o de alto costo.

Todo el código que importa esta configuración hoy puede estar escrito en Python, y puede pensar que esto también será cierto mañana, pero ¿está seguro?

Dijiste que usarías lógica (cualquier otra cosa que no sean estructuras de datos estáticos) en tu configuración con moderación, si es que es bueno, pero si hay algo de eso, te resultará difícil deshacerlo en el futuro para que puedas puede volver a un archivo de configuración declarativo.

EDITAR para el registro: varias personas han comentado sobre esta respuesta acerca de cuán probable o improbable es que un proyecto se reescriba completamente en otro idioma. Es justo decir que una reescritura completa compatible con versiones anteriores probablemente rara vez se ve. Lo que realmente tenía en mente era que partes del mismo proyecto (y que necesitaban acceso a la misma configuración) se escribieran en diferentes idiomas. Por ejemplo, servir pila en C ++ para velocidad, limpieza de bases de datos por lotes en Python, algunos scripts de shell como pegamento. Así que también piense en ese caso :)

Celada
fuente
1
@Mast, disculpas, pero no te sigo. El nombre del archivo (ya sea que termine o no en .py) no está ni aquí ni allí. El punto que estoy tratando de hacer es que si está escrito en Python, entonces necesitas un intérprete de Python para leerlo.
Celada
12
@Mast Creo que lo estás analizando mal. El punto que tomé de esta respuesta (tanto original como editado) es que la elección de escribir archivos de configuración en un lenguaje de programación es que hace que sea más difícil escribir código en otro idioma. Por ejemplo, decide portar su aplicación a Anrdoid / iPhone y utilizará otro idioma. Debe (a) confiar en un intérprete de Python en la aplicación del teléfono móvil (no es ideal), (b) reescribir la configuración en un formato independiente del idioma y reescribir el código de Python que la utilizó, o (c) mantener dos formatos de configuración en el futuro.
Jon Bentley
44
@ JonBentley Supongo que la preocupación será relevante si hay planes para hacer proyectos en varios idiomas. No recibí esa impresión del OP. Además, el uso de archivos de texto para la configuración aún requiere un código adicional (en todos los idiomas) para el análisis / conversión de valores reales. Técnicamente, si limitan el lado de Python a las key=valueasignaciones para la configuración, no veo por qué un programa Java / C ++ no puede leer el archivo Python como un archivo de texto sin formato y analizarlo de la misma manera si necesitan pasar a otra cosa en el futuro. No veo la necesidad de un intérprete completo de Python.
code_dredd
3
@ray Verdadero, pero la respuesta sigue siendo útil porque las preguntas no deberían ser solo aplicables a la persona que las publica. Si utiliza un formato estandarizado (por ejemplo, INI, JSON, YAML, XML, etc.), probablemente utilizará una biblioteca de análisis existente en lugar de escribir la suya. Eso reduce el trabajo adicional a solo una clase de adaptador para interactuar con la biblioteca de análisis. Si se limita a key = value, eso elimina la mayoría de las razones del OP para usar Python en primer lugar y también podría ir con un formato reconocido.
Jon Bentley
3
Tuve que hacer esto hace unos años cuando una herramienta escrita en Lua usaba el script de Lua como sus configuraciones, luego querían que escribiéramos una nueva herramienta en C #, y específicamente nos pidieron que usáramos el script de configuración de Lua. Tenían un total de 2 líneas que en realidad eran programables y no simples x = y, pero aún así tuve que aprender sobre los intérpretes de Lua de código abierto para .net debido a ellos. No es un argumento puramente teórico.
Kevin Fee
21

Las otras respuestas ya son muy buenas, solo aportaré mi experiencia del uso en el mundo real en algunos proyectos.

Pros

En su mayoría ya están detallados:

  • si está en un programa de Python, el análisis es muy sencillo ( eval); funciona automáticamente incluso para tipos de datos más complejos (en nuestro programa, tenemos puntos geométricos y transformaciones, que se descargan / cargan perfectamente a través de repr/ eval);
  • crear una "configuración falsa" con solo unas pocas líneas de código es trivial;
  • tiene mejores estructuras y, en mi opinión, una sintaxis mucho mejor que JSON (por Dios, incluso tener comentarios y no tener que poner comillas dobles alrededor de las teclas del diccionario es una gran ganancia de legibilidad).

Contras

  • los usuarios malintencionados pueden hacer cualquier cosa que pueda hacer su programa principal; No considero que sea un gran problema, ya que generalmente si un usuario puede modificar un archivo de configuración, él / ella ya puede hacer lo que la aplicación pueda hacer;
  • si ya no estás en un programa de Python, ahora tienes un problema. Si bien varios de nuestros archivos de configuración permanecieron privados para su aplicación original, uno en particular vino a almacenar información que utilizan varios programas diferentes, la mayoría de los cuales se encuentran actualmente en C ++, que ahora tienen un analizador pirateado para un pequeño mal definido subconjunto de Python repr. Obviamente esto es algo malo.
  • Incluso si su programa permanece en Python, puede cambiar la versión de Python. Digamos que su aplicación comenzó en Python 2; después de muchas pruebas, logró migrarlo a Python 3; desafortunadamente, realmente no probó todo su código, tiene todos los archivos de configuración en las máquinas de sus clientes, escritos para Python 2, y en los que no Realmente no tengo control. ¡Ni siquiera puede proporcionar un "modo de compatibilidad" para leer archivos de configuración antiguos (que a menudo se hace para formatos de archivo), a menos que esté dispuesto a agrupar / llamar al intérprete de Python 2!
  • Incluso si está en Python, modificar el archivo de configuración desde el código es un problema real, porque ... bueno, modificar el código no es trivial en absoluto, especialmente el código que tiene una sintaxis rica y no está en LISP o similar. Uno de nuestros programas tiene un archivo de configuración que es Python, originalmente escrito a mano, pero que luego resultó ser útil para manipular a través del software (una configuración particular es una lista de cosas que es mucho más fácil reordenar usando una GUI). Este es un gran problema, porque:

    • incluso solo realizar un análisis → AST → reescribir viaje de ida y vuelta no es trivial (notará que la mitad de las soluciones propuestas luego se marcan como "obsoletas, no usar, no funcionan en todos los casos");
    • incluso si funcionaran, AST es demasiado bajo nivel; generalmente está interesado en manipular el resultado de los cálculos realizados en el archivo, no los pasos que lo llevaron;
    • lo que nos lleva al simple hecho de que no puede simplemente editar los valores que le interesan, ya que pueden generarse por algún cálculo complejo que no puede comprender / manipular a través de su código.

    Compare esto con JSON, INI o (¡Dios no lo quiera!) XML, donde la representación en memoria siempre se puede editar y volver a escribir sin pérdida de datos (XML, donde la mayoría de los analizadores DOM pueden mantener espacios en blanco en nodos de texto y nodos de comentarios) o al menos perder solo un poco de formato (JSON, donde el formato en sí mismo no permite mucho más que los datos sin procesar que está leyendo).


Entonces, como siempre, no hay una solución clara; mi política actual sobre el tema es:

  • si el archivo de configuración es:

    • seguramente para una aplicación Python y privada, como en, nadie más intentará leer de ella;
    • escrito;
    • viniendo de una fuente confiable;
    • el uso de tipos de datos de aplicaciones de destino es realmente una ventaja

    un archivo Python puede ser una idea válida;

  • si en cambio:

    • puede existir la posibilidad de que lean alguna otra aplicación;
    • existe la posibilidad de que este archivo pueda ser editado por una aplicación, posiblemente incluso por mi propia aplicación;
    • es proporcionado por una fuente no confiable.

    un formato de "solo datos" puede ser una mejor idea.

Tenga en cuenta que no es necesario hacer una elección única: recientemente escribí una aplicación que usa ambos enfoques. Tengo un archivo casi nunca modificado con configuraciones manuscritas de primera configuración donde hay ventajas de tener bonificaciones bonificadas de Python y un archivo JSON para la configuración editada desde la interfaz de usuario.

Matteo Italia
fuente
1
¡Muy buen punto sobre generar o reescribir config! Pero pocos formatos que no sean XML pueden retener comentarios en la salida, lo que considero extremadamente importante para la configuración. Otros formatos a veces introducen un note:campo que se ignora para la configuración.
amon
2
"si un usuario puede modificar un archivo de configuración, él / ella ya puede hacer lo que la aplicación pueda hacer", esto no es del todo cierto. ¿Qué tal probar que el brillante archivo de configuración que alguien que no conoces ha subido en pastebin?
Dmitry Grigoryev
2
@DmitryGrigoryev: si está apuntando a ese objetivo, también puede decirle a su víctima que copie y pegue algunos curl ... | bash, es aún menos molesto. :-P
Matteo Italia
@DmitryGrigoryev: y es el tipo de cosa que podría permitir a alguien destruir por completo un sistema de producción en su primer día en el trabajo. Si 'eval' es su analizador, eso significa que no hay oportunidad de verificar si hay problemas antes de leerlo. (la misma razón por la que los scripts de shell son tan malos en producción). INI, YAML o JSON son seguros a este respecto.
Joe
1
@DmitryGrigoryev: mi punto es que si su tipo de víctima es lo suficientemente estúpido como para copiar y pegar ciegamente un archivo de configuración, probablemente pueda engañarlo para que haga lo que sea en su máquina con métodos menos oblicuos ("pegue esto en una consola para ¡arregla tu problema! "). Además, incluso con archivos de configuración no ejecutables, existe un gran potencial de daño, incluso solo apuntando maliciosamente el registro sobre archivos críticos (si la aplicación se ejecuta con suficientes privilegios) puede causar estragos en el sistema. Esa es la razón por la que creo que en la práctica no hay mucha diferencia en términos de seguridad.
Matteo Italia
8

La pregunta principal es: ¿desea que su archivo de configuración esté en algún lenguaje completo de Turing (como Python)? Si lo desea, también puede considerar incrustar algún otro lenguaje de script (Turing completo) como Guile o Lua (porque podría percibirse como "más simple" usar o incrustar que Python; lea el capítulo sobre Extensión y Incrustación de Python ). No lo discutiré más a fondo (porque otras respuestas, por ejemplo, Amon , lo discutieron en profundidad), pero tenga en cuenta que incrustar un lenguaje de secuencias de comandos en su aplicación es una elección arquitectónica importante , que debe considerar muy pronto; ¡Realmente no recomiendo hacer esa elección más tarde!

Un ejemplo bien conocido de un programa configurable a través de "scripts" es el editor GNU emacs (o probablemente AutoCAD en el dominio propietario); así que tenga en cuenta que si acepta las secuencias de comandos, algún usuario eventualmente usaría, y quizás abusaría, en su punto de vista, esa facilidad ampliamente y crearía una secuencia de comandos de miles de líneas; por lo tanto, la elección de un lenguaje de script suficientemente bueno es importante.

Sin embargo (al menos en los sistemas POSIX), usted podría considerar conveniente para que el "archivo" de configuración para ser dinámicamente calculada en tiempo de inicialización (por supuesto, dejando la carga de una configuración de cuerdo a su administrador del sistema o usuario, en realidad se trata de una configuración texto que proviene de algún archivo o de algún comando). Para eso, simplemente podría adoptar la convención (y documentarla ) de que una ruta de archivo de configuración que comienza con, por ejemplo, !ao a |es en realidad un comando de shell que leería como una tubería . Esto deja a su usuario la opción de usar cualquier "preprocesador" o "lenguaje de script" con el que esté más familiarizado.

(debe confiar en su usuario sobre los problemas de seguridad si acepta una configuración calculada dinámicamente)

Entonces, en su código de inicialización, su main(por ejemplo) aceptaría algún --config argumento confarg y obtendría algo FILE*configf;de él. Si ese argumento comienza con !(es decir, si (confarg[0]=='!')...), usaría configf = popen(confarg+1, "r");y cerraría esa tubería con pclose(configf);. De lo contrario, usaría configf=fopen(confarg, "r");y cerraría ese archivo con fclose(configf);(no olvide la comprobación de errores). Ver tubo (7) , popen (3) , fopen (3) . Para una aplicación codificada en Python, lea sobre os.popen , etc.

(documento también para el usuario extraño que desea pasar un archivo de configuración llamado !foo.configa pasar ./!foo.configpara evitar el popentruco anterior)

Por cierto, tal truco es solo una conveniencia (para evitar que el usuario avanzado, por ejemplo, codifique algún script de shell para generar un archivo de configuración ). Si el usuario desea informar cualquier error, debe enviarle el archivo de configuración generado ...

Tenga en cuenta que también puede diseñar su aplicación con la capacidad de usar y cargar complementos en el momento de la inicialización, por ejemplo, con dlopen (3) (y debe confiar en su usuario acerca de ese complemento). Nuevamente, esta es una decisión arquitectónica muy importante (y debe definir y proporcionar una API y una convención bastante estables sobre estos complementos y su aplicación).

Para una aplicación codificada en un lenguaje de script como Python, también podría aceptar algún argumento de programa para eval o exec o primitivas similares. Una vez más, los problemas de seguridad son la preocupación del usuario (avanzado) .

Con respecto al formato de texto para su archivo de configuración (ya sea generado o no), creo que en su mayoría necesita documentarlo bien (y la elección de algún formato en particular no es tan importante; sin embargo, le recomiendo permitir que su usuario pueda poner algunos comentarios omitidos en su interior). Puede usar JSON (preferiblemente con algún analizador JSON que acepte y omita comentarios con //eol habitual o /*... */...), YAML, XML o INI o lo suyo. Analizar un archivo de configuración es razonablemente fácil (y encontrará muchas bibliotecas relacionadas con esa tarea).

Basile Starynkevitch
fuente
+1 por mencionar la integridad de Turing de los lenguajes de programación. Algunos trabajos interesantes revelan que limitar la potencia computacional del formato de entrada es clave para asegurar la capa de manejo de entrada. El uso de un lenguaje de programación completo de Turing va en la dirección opuesta.
Matheus Moreira
2

Además de la respuesta de amon , ¿ha considerado alternativas? JSON es quizás más de lo que necesita, pero los archivos de Python probablemente le darán problemas en el futuro por las razones mencionadas anteriormente.

Sin embargo, Python ya tiene un analizador de configuración para un lenguaje de configuración muy simple que puede satisfacer todas sus necesidades. El ConfigParsermódulo implementa un lenguaje de configuración simple.

CodeMonkey
fuente
1
Usar algo 'similar a ... archivos INI de Microsoft Windows' parece ser una mala idea, ya que no es un formato particularmente flexible y porque 'similar' implica incompatibilidades indocumentadas.
Pete Kirkham
1
@PeteKirkham Bueno, es simple, está documentado y es parte de la biblioteca estándar de Python. Podría ser la solución perfecta para las necesidades de los OP, porque está buscando algo que sea compatible directamente con Python y que sea más simple que JSON. Mientras no especifique cuáles son sus necesidades, creo que esta respuesta puede ser útil para él.
CodeMonkey
1
Iba a sugerir esencialmente esto: ver qué tipos de archivos de configuración admiten las bibliotecas de Python y elegir uno de esos. Además, Powershell tiene la noción de secciones de datos, que permiten construcciones de lenguaje Powershell limitadas, protegiendo contra código malicioso. Si Python tiene una lib que admite un subconjunto limitado de Python para la configuración, eso al menos mitiga uno de los inconvenientes contra la idea en el OP.
ẘpẘ
1
@PeteKirkham Es más probable que sea un problema al revés. Windows tiende a tener un montón de basura indocumentada que explota en ti. Python tiende a estar bien documentado y directo. Dicho esto, si todo lo que necesita son simples pares clave / valor ( tal vez con secciones), es una muy buena opción. Sospecho que esto cubre el 90% de los casos de uso. Si los archivos de configuración de .NET fueran ini en lugar del monstruoso XML con un esquema que en realidad es un código disfrazado de configuración, todos estaríamos mucho mejor.
jpmc26
1
@PeteKirkham No realmente. INI es el mejor para casos de uso simple en primer lugar, lo más probable es que pueda evitar cualquier incompatibilidad. Tampoco importan si no está consumiendo el archivo con dos idiomas diferentes, e incluso si lo está, probablemente pueda encontrar implementaciones abiertas en cualquier idioma (lo que le permite no tener incompatibilidades o, como mínimo, saber exactamente qué son). Estoy de acuerdo en que debe usar otro formato si su caso de uso es realmente lo suficientemente complejo como para comenzar a toparse con ellos o si no puede encontrar una implementación existente en la que pueda confiar, pero eso no es común.
jpmc26
1

He trabajado durante mucho tiempo con un software conocido que tiene sus archivos de configuración escritos en TCL, por lo que la idea no es nueva. Esto funcionó bastante bien, ya que los usuarios que no conocían el idioma aún podían escribir / editar archivos de configuración simples usando una sola set name valuedeclaración, mientras que los usuarios y desarrolladores más avanzados podrían hacer trucos sofisticados con esto.

No creo que "los archivos de configuración puedan ser difíciles de depurar" es una preocupación válida. Siempre que su aplicación no obligue a los usuarios a escribir scripts, sus usuarios siempre pueden usar asignaciones simples en sus archivos de configuración, lo que difícilmente es más difícil de hacer en comparación con JSON o XML.

Reescribir la configuración es un problema, aunque no es tan malo como parece. Es imposible actualizar el código arbitrario, pero cargar la configuración desde un archivo, alterarlo y guardarlo nuevamente. Básicamente, si realiza algunas secuencias de comandos en un archivo de configuración que no es de solo lectura, terminará con una lista equivalente de set name valuedeclaraciones una vez que se guarde. Una buena pista de que esto sucederá es un comentario de "no editar" al comienzo del archivo.

Una cosa a tener en cuenta es que sus archivos de configuración no serán legibles de manera confiable mediante herramientas simples basadas en expresiones regulares, como sed, por lo que entiendo, este ya no es el caso con sus archivos JSON actuales, por lo que no hay mucho que perder.

Solo asegúrese de utilizar las técnicas de sandboxing adecuadas al ejecutar sus archivos de configuración.

Dmitry Grigoryev
fuente
1
"Software" es un sustantivo incontable, por lo que debería ser " algún software conocido".
jpmc26
1

Además de todos los puntos válidos de otras buenas respuestas aquí (wow, incluso mencionaron el concepto completo de Turing), en realidad hay un par de razones prácticas sólidas para NO usar un archivo Python como su configuración, incluso cuando está trabajando en un Python- solo proyecto.

  1. La configuración dentro de un archivo fuente de Python es técnicamente parte del código fuente ejecutable, en lugar de un archivo de datos de solo lectura. Si sigue esta ruta, normalmente lo haría import config, porque ese tipo de "conveniencia" fue presumiblemente una de las principales razones por las que las personas comenzaron a usar un archivo Python como configuración en primer lugar. Ahora tiende a asignar ese config.py en su repositorio, de lo contrario, su usuario final se encontrará con un ImportError confuso cuando intente ejecutar su programa por primera vez.

  2. Asumiendo que realmente está comprometiendo ese config.py en su repositorio, ahora los miembros de su equipo probablemente tendrían diferentes configuraciones en diferentes entornos. Imagine que algún día, de algún modo, algún miembro ingresa accidentalmente su archivo de configuración local en el repositorio.

  3. Por último, pero no menos importante, su proyecto podría tener contraseñas en el archivo de configuración. (Esta es una práctica discutible en sí misma, pero ocurre de todos modos). Y si su archivo de configuración existe en el repositorio, corre el riesgo de comprometer su credencial en un repositorio público.

Ahora, el uso de un archivo de configuración de solo datos, como el formato JSON universal, puede evitar los 3 problemas anteriores, porque razonablemente puede pedirle al usuario que presente su propio config.json y lo incorpore a su programa.

PD: Es cierto que JSON tiene muchas restricciones. 2 de las limitaciones mencionadas por el OP, se pueden resolver con un poco de creatividad.

RayLuo
fuente