Як погано ідея використовувати файли Python як файли конфігурації?


72

Я завжди використовував файли JSON для конфігурації своїх додатків. Я почав використовувати їх з того часу, коли я кодував багато Java, і тепер я працюю в основному над розробкою Python на стороні сервера та інформацією про дані, і я не впевнений, чи JSON - це правильний шлях.

Я бачив, як Celery використовує фактичні файли Python для конфігурації. Спочатку я скептично ставився до цього. Але ідея використовувати прості структури даних Python для конфігурації на мене починає рости. Деякі плюси:

  • Структури даних будуть такими ж, як я зазвичай кодую. Отже, мені не потрібно змінювати думки.
  • Мій IDE (PyCharm) розуміє зв'язок між конфігурацією та кодом. Ctrl+ Bдозволяє легко переходити між конфігурацією та кодом.
  • Мені не потрібно працювати з ІМО непотрібним суворим JSON . Я дивлюся на вас подвійні цитати, ніяких зворотних коми та жодних коментарів.
  • Я можу записати тестові конфігурації у програмі, над якою працюю, а потім легко перенести їх у файл конфігурації без необхідності будь-якого перетворення та розбору JSON.
  • Можна зробити дуже простий сценарій у файлі конфігурації, якщо це дійсно необхідно. (Хоча це має бути дуже, дуже обмежено.)

Отже, моє питання: Якщо я перемикаюся, як я стріляю собі в ногу?

Жоден некваліфікований кінцевий користувач не буде використовувати файли конфігурації. Будь-які зміни у файлах конфігурації наразі здійснюються в Git і передаються на наші сервери в рамках постійного розгортання. Жодних змін в конфігурації вручну немає, якщо немає надзвичайної ситуації або вона знаходиться в стадії розробки.

(Я розглядав YAML , але щось із цього мене дратує. Отже, поки що він не за американським столом.)


39
Некваліфікований - не ваша проблема. Злісно є.
Blrfl

9
Що ви маєте на увазі під «американським столом» ?
Пітер Мортенсен

24
"Отже, поки що це поза американським столом". === "Отже, поки що це, як кажуть американці, поза столом."
єпископ

7
Якщо ви не любите JSON, спробуйте yaml. Мені це дуже подобається за налаштуваннями. особливо коли задіяні більші рядки, YAML є більш зрозумілим, ніж JSON.
Крістіан Зауер

5
@ bishop "з-за столу" у Великобританії англійською мовою більше не розглядається, оскільки парламентські пропозиції ставляться на стіл посеред Палати громад для довідки при обговоренні, отже, також "виноситься на обговорення" (запис парламенту 1799 - books.google.co.uk/… ), AFAIK в США значення однакове, але я не знаю, чи є у вас стіл у парламенті.
Піт Кіркхем,

Відповіді:


92

Використання мови скриптів замість конфігураційного файлу на перший погляд виглядає чудово: у вас є вся потужність цієї мови, і ви можете просто eval()чи importнею. На практиці є декілька готчей:

  • це мова програмування, яку потрібно вивчити. Щоб відредагувати конфігурацію, ви повинні досить добре знати цю мову. Файли конфігурації зазвичай мають більш простий формат, який складніше помилитися.

  • це мова програмування, а це означає, що конфіг може отримати важку налагодження. У звичайному конфігураційному файлі ви дивитесь на нього і бачите, які значення надаються для кожного ресурсу. Зі скриптом вам, можливо, потрібно спочатку виконати його, щоб побачити значення.

  • це мова програмування, що ускладнює збереження чіткого поділу між конфігурацією та фактичною програмою. Іноді ви хочете такого розширення, але в цей момент ви, швидше за все, шукаєте справжню систему плагінів.

  • це мова програмування, що означає, що конфігурація може робити все, що може зробити мова програмування. Отже, або ви використовуєте рішення пісочниці, яке заперечує значну гнучкість мови, або ви довіряєте автору конфігурації.

Тому використання сценарію для конфігурації, ймовірно, добре, якщо аудиторія вашого інструменту - це розробники, наприклад, Sphinx config або setup.py в проектах Python. Інші програми з виконуваною конфігурацією - це оболонки, такі як Bash, і такі редактори, як Vim.

Використовувати мову програмування для конфігурації необхідно, якщо конфігурація містить багато умовних розділів або якщо вона забезпечує зворотні виклики / плагіни. Використання скрипту безпосередньо замість eval () - деяке поле конфігурації, як правило, більш налагоджувальне (подумайте про сліди стека та номери рядків!).

Безпосередньо використання мови програмування також може бути хорошою ідеєю, якщо ваш конфігурація настільки повторюється, що ви пишете сценарії для автогенерації конфігурації. Але, можливо, краща модель даних для конфігурації могла б усунути необхідність такої явної конфігурації? Наприклад, це може бути корисно, якщо файл конфігурації може містити заповнювачі, які ви згодом розгорнете. Іншою особливістю, яку іноді можна побачити, є кілька конфігураційних файлів з різним пріоритетом, які можуть перекривати один одного, хоча це вводить власні проблеми.

У більшості випадків файли INI, файли властивостей Java або документи YAML набагато краще підходять для конфігурації. Для складних моделей даних також може застосовуватися XML. Як ви зазначали, JSON має деякі аспекти, які роблять його непридатним як конфігураційний файл, редагований людиною, хоча це прекрасний формат обміну даними.


25
Є кілька форматів файлів конфігурації, які "випадково завершені Тьюрінгом", найвідоміше sendmail.cf. Це вказувало б на те, що використання фактичної мови сценаріїв може бути корисним, оскільки ця мова була фактично розроблена як повний Тьюрінг. Однак Тюрінг-повнота та "Тетріс-повнота" - це дві різні речі, і, хоча sendmail.cfможе обчислити довільні функції, він не може надсилати вашу /etc/passwdмережу чи форматувати ваш жорсткий диск, який Python чи Perl змогли б.
Йорг W Міттаг

3
@ JörgWMittag Турінська завершеність не передбачає можливості надсилати речі по мережі або отримувати доступ до жорсткого диска. Тобто, туринська повнота полягає в обробці не про вводу / виводу. Наприклад, CSS вважається Туріном завершеним, але він не зіпсується з вашим постійним сховищем. Ви казали деінде, що «Ідріс - це ціла чиста функціональна мова, тому вона за визначенням не є цілковитою Тюрінгом», що не випливає, і, мабуть, це Турин повний. Я був переконаний, що використання тестового тесту означало, що мова є туринською, але не в змозі зробити повний введення / вивід ... здається, це не те, що ви маєте на увазі.
Тераот

6
@Theraot: "Всього" означає, що вона завжди повертається. Машина Тьюрінга може виконувати нескінченний цикл, тобто має здатність не повертатися. Ерго, Ідріс не може зробити все, що робить машина Тюрінга, а це означає, що це не є Тьюрінгом. Це стосується всіх мов, що залежать від типу. Вся суть мови, що залежить від типу, полягає в тому, що ви можете визначати довільні властивості щодо програм, тоді як в мові, що повністю закінчується Тьюрінгом, ви навіть не можете визначити тривіальні властивості, такі як "чи зупиняється ця програма?" Загальні мови за визначенням не є повними Тьюрінга, оскільки машини Тьюрінга є частковими.
Йорг W Міттаг

10
Визначення з «Тьюринга» є «може реалізувати Тьюринг машин». Визначення "повний тетріс" - "може реалізувати тетріс". Вся суть цього визначення полягає в тому, що Тюрінг-повнота просто не дуже цікава в реальному світі. Є безліч корисних мов, які не завершені Тьюрінгом, наприклад, HTML, SQL (до 1999 року), різні DSL тощо. OTOH, повнота Тьюрінга означає лише те, що ви можете обчислювати функції через натуральні числа, це не означає друк на екран, доступ до мережі, взаємодія з користувачем, ОС, середовищем, і все це важливо.
Йорг W Міттаг

4
Причина, чому Едвін Брейді застосував цей приклад, полягає в тому, що багато людей думають, що мови, які не завершені Тьюрінгом, не можна використовувати для програмування загального призначення. Я сам думав, що теж, адже зрештою, багато цікавих програм є по суті нескінченними циклами, які ми не хочемо зупиняти , наприклад, сервери, операційні системи, петлі подій у графічному інтерфейсі, ігрові петлі. Багато програм обробляють нескінченні дані, наприклад, потоки подій. Раніше я думав, що ви не можете написати це загальною мовою, але з тих пір я дізнався, що ви можете , і тому вважаю гарною ідеєю мати термін для цієї можливості.
Йорг W Міттаг

50

+1 до всього , що відповідає у відповідь Амона . Я хочу додати це:

Ви пошкодуєте, використовуючи код Python як мову конфігурації, коли ви вперше імпортуєте ту саму конфігурацію з коду, написаного іншою мовою. Наприклад, якщо код, який є частиною вашого проекту, і він написаний на C ++ або Ruby, або щось інше потрібно витягнути в конфігурацію, вам потрібно буде зв’язати інтерпретатор Python як бібліотеку або проаналізувати конфігурацію в копроцесі Python, обидва які незручні, важкі або з високим рівнем витрат.

Весь код, який імпортує цю конфігурацію сьогодні, може бути написаний на Python, і ви можете подумати, що це буде правдою і завтра, але чи знаєте ви точно?

Ви сказали, що використовуєте логіку (будь-що інше, ніж статичні структури даних) у вашій конфігурації, якщо це зовсім добре, але це добре, але якщо в цьому є якийсь біт, вам в майбутньому буде важко скасувати його, щоб ви може повернутися до декларативного файлу конфігурації.

EDIT для запису: кілька людей прокоментували цю відповідь про те, наскільки ймовірно чи малоймовірно, що проект коли-небудь буде успішно повністю переписаний іншою мовою. Справедливо сказати, що повне перезапис, сумісний із зворотним ходом, напевно рідко зустрічається. Насправді я мав на увазі, що шматочки та фрагменти одного проекту (і потребують доступу до тієї ж конфігурації) написані різними мовами. Наприклад, що обслуговує стек в C ++ для швидкості, пакетне очищення бази даних в Python, деякі сценарії оболонки як клей. Тож витрачайте думки і на цей випадок :)


1
@Маст, вибачте, але я не дотримуюся. Назва файлу (чи закінчується він у .py) ні тут, ні там. Я намагаюся зробити, що якщо це написано в Python, то для його читання вам потрібен інтерпретатор Python.
Челада

12
@ Мабуть, я думаю, ти неправильно розбираєш Точка, яку я взяв із цієї відповіді (як оригінальної, так і відредагованої), полягає в тому, що вибір запису файлів конфігурації мовою програмування полягає в тому, що це ускладнює запис коду іншою мовою. Наприклад, ви вирішили перенести додаток на Anrdoid / iPhone і будете використовувати іншу мову. Вам або потрібно (a) покластися на інтерпретатора Python у додатку для мобільних телефонів (не ідеально), (b) переписати конфігурацію у незалежному від мови форматі та переписати код Python, який використовував її, або (c) підтримувати два формати конфігурації, що рухаються вперед.
Джон Бентлі

4
@JonBentley Я вважаю, що проблема буде актуальною, якщо ви плануєте робити багатомовні проекти. Я не мав такого враження від ОП. Крім того, для використання текстових файлів для конфігурації ще потрібен додатковий код (на всіх мовах) для фактичного розбору / перетворення значень. Технічно, якщо вони обмежують сторону Python key=valueпризначеннями для конфігурації, я не бачу, чому програма Java / C ++ не змогла прочитати файл Python як звичайний текстовий файл і проаналізувати його так само, якщо їм потрібно перейти до чогось іншого в майбутнє. Я не бачу потреби в повноцінному перекладачі Python.
code_dredd

3
@ray Правда, але відповідь все ж корисна, виходячи з того, що питання не повинні стосуватися лише того, хто їх публікує. Якщо ви використовуєте стандартизований формат (наприклад, INI, JSON, YAML, XML тощо), то, швидше за все, ви будете використовувати існуючу бібліотеку розбору, а не писати власну. Це зводить додаткову роботу лише до класу адаптера для інтерфейсу з бібліотекою розбору. Якщо ви обмежуєте себе key = value, то це усуває більшість причин ОП для використання Python в першу чергу, і ви також можете просто перейти з розпізнаним форматом.
Джон Бентлі

3
Мені довелося це зробити кілька років тому, коли інструмент, написаний на Lua, використовував скрипт Lua в якості своїх конфігурацій, тоді вони хотіли, щоб ми написали новий інструмент в C #, і спеціально попросили нас використовувати сценарій конфігурації Lua. У них було всього 2 рядки, які насправді були програмованими та не простими x = y, але мені все-таки довелося дізнатися про інтерпретатори Lua з відкритим кодом для .net через них. Це не чисто теоретичний аргумент.
Кевін Плата

21

Інші відповіді вже дуже хороші, я просто наведу свій досвід використання в реальному світі в кількох проектах.

Плюси

В основному вони вже прописані:

  • якщо ви перебуваєте в програмі Python, синтаксичний аналіз - це вітер ( eval); він працює автоматично навіть для більш складних типів даних (у нашій програмі у нас є геометричні точки та перетворення, які скидаються / завантажуються просто добре через repr/ eval);
  • створення "підробленої конфігурації" лише з декількома рядками коду тривіально;
  • у вас кращі структури і, IMO, синтаксис краще, ніж JSON (навіть якщо мати коментарі та не потрібно ставити подвійні лапки навколо словникових клавіш - це велика перемога).

Мінуси

  • зловмисні користувачі можуть робити все, що може зробити ваша основна програма; Я не вважаю це великою проблемою, оскільки, як правило, якщо користувач може змінити файл конфігурації, він / вона вже може робити все, що може зробити програма;
  • якщо ви більше не користуєтесь програмою Python, тепер у вас є проблема. Хоча декілька наших конфігураційних файлів залишалися приватними до їх первісного додатка, один, зокрема, прийшов для зберігання інформації, яка використовується декількома різними програмами, більшість з яких зараз перебуває на C ++, які тепер мають зламаний аналізатор для неправильно визначеного малого підмножина Python repr. Це, очевидно, погано.
  • Навіть якщо ваша програма залишається в Python, ви можете змінити версію Python. Скажімо, ваша заявка розпочалася в Python 2; після безлічі тестувань вам вдалося перенести його на Python 3 - на жаль, ви насправді не перевірили весь код - у вас є всі файли конфігурації, що лежать на машинах ваших клієнтів, написані для Python 2 і на яких ви не працюєте У мене справді немає контролю. Ви навіть не можете надати "режим сумісності" для читання старих файлів конфігурації (що часто робиться для форматів файлів), якщо ви не готові поєднати / викликати інтерпретатора Python 2!
  • Навіть якщо ви перебуваєте в Python, зміна файлу конфігурації з коду є справжньою проблемою, тому що ... ну, зміна коду зовсім не тривіальна, особливо код, який має багатий синтаксис і не є в LISP чи подібному. Одна з програм , наша має конфігураційний файл, Python, спочатку написаний вручну, але потім виявилося, було б корисно , щоб маніпулювати з допомогою програмного забезпечення (конкретна установка являє собою список речей , які є спосіб простіше змінити порядок з допомогою графічного інтерфейсу користувача). Це велика проблема, оскільки:

    • навіть виконання синтаксичного аналізу → AST → переписати турецький перехід не є тривіальним (ви помітите, що половина запропонованих рішень пізніше позначені як «застарілі, не використовуйте, працює не у всіх випадках»);
    • навіть якщо вони працювали, AST занадто низький; ви, як правило, зацікавлені в маніпулюванні результатом обчислень, що виконуються у файлі, а не кроками, які були доведені до нього;
    • що підводить нас до простого факту, що ви не можете просто редагувати цікавлять вас значення, оскільки вони можуть бути породжені складними обчисленнями, які ви не можете зрозуміти / маніпулювати за допомогою коду.

    Порівняйте це з JSON, INI або (не дай Бог!) XML, де представлення в пам'яті завжди можна редагувати і записувати назад без втрати даних (XML, де більшість парсерів DOM можуть зберігати пробіл у текстових вузлах та вузлах коментарів) або принаймні втратити лише деяке форматування (JSON, де сам формат не дозволяє набагато більше, ніж необроблені дані, які ви читаєте).


Отже, як завжди, немає чіткого рішення; моя поточна політика щодо цього питання:

  • якщо файл конфігурації:

    • безумовно, для додатку Python і приватного до нього - як і в ніхто більше ніколи не спробує прочитати з нього;
    • рукописний;
    • походить від надійного джерела;
    • використання цільових типів даних програм - це справді премія;

    файл Python може бути дійсною ідеєю;

  • якщо замість цього:

    • може бути можливість прочитати з нього якусь іншу програму;
    • є можливість, що цей файл може бути відредагований програмою, можливо, навіть моєю програмою;
    • надається ненадійним джерелом.

    формат "лише для даних" може бути кращою ідеєю.

Зауважте, що робити один вибір не потрібно - я нещодавно написав заявку, яка використовує обидва підходи. У мене є майже ніколи не модифікований файл із першими налаштуваннями, рукописними налаштуваннями, де є переваги отримання хороших бонусів Python та файлу JSON для конфігурації, відредагованої з інтерфейсу користувача.


1
дуже хороший момент щодо створення або переписування конфігурації! Але деякі формати, окрім XML, можуть зберігати коментарі у висновку, що я вважаю надзвичайно важливим для конфігурації. Інші формати інколи вводять note:поле, яке ігнорується для конфігурації.
амон

2
"якщо користувач може змінити файл конфігурації, він / вона вже може робити все, що може зробити програма" - це не зовсім так. Як щодо тестування, ніж блискучий конфігураційний файл, який хтось, кого ви не знаєте, завантажив на пастебін?
Дмитро Григор’єв

2
@DmitryGrigoryev: якщо ви прагнете до цієї цілі, ви можете також сказати своїй жертві скопіювати і вставити деякі curl ... | bash, це ще менше клопоту. :-P
Маттео Італія

@DmitryGrigoryev: і саме тип речі може дозволити комусь повністю зруйнувати виробничу систему в перший день роботи. Якщо 'eval' є вашим парсером, це означає, що немає можливості перевірити його на наявність проблем перед його читанням. (та сама причина, чому сценарії оболонок настільки погані у виробництві). INI, YAML або JSON в цьому плані безпечні.
Джо

1
@DmitryGrigoryev: моя думка полягає лише в тому, що якщо ваш тип жертви досить дурний, щоб сліпо скопіювати і вставити файл конфігурації, ви, ймовірно, можете його обдурити робити все, що на їх машині, за допомогою менш косих методів ("вставити це в консоль для виправити свою проблему! "). Крім того, навіть у файлах конфігурації, що не виконуються, існує велика небезпека - навіть просто зловмисне вказівка ​​входу в систему критичних файлів (якщо програма працює з достатньою кількістю привілеїв), ви можете завдати шкоди системі. Ось чому я вважаю, що на практиці це не велика різниця в умовах безпеки.
Маттео Італія

8

Головне питання: чи хочете, щоб ваш конфігураційний файл був на якійсь мові Тьюрінга (як Python)? Якщо ви цього хочете, ви можете також розглянути можливість вбудовування будь-якої іншої мови (сценарій Тюрінга), такої як Guile або Lua (оскільки там можна сприймати як "простіший" для використання або вбудовування, ніж Python; читайте розділ Розширення & Вбудовування Python ). Я не буду це обговорювати далі (тому що інші відповіді - наприклад , Амон - обговорювали це глибоко), але зауважу, що вбудованість мови сценаріїв у ваш додаток є головним архітектурним вибором , про який слід розглянути дуже рано; Я дійсно не рекомендую робити цей вибір пізніше!

Добре відомий приклад налаштування програми через "скрипти" - це редактор GNU emacs (або, можливо, AutoCAD у власній царині); тож майте на увазі, що якщо ви приймете сценарій, якийсь користувач врешті-решт використовуватиме - і, можливо, зловживає, з точки зору вашої точки зору - цей інструмент і зробить сценарій з багатотисячним рядком; тому вибір важливої ​​мови сценаріїв є важливим.

Однак (принаймні, в системах POSIX), ви можете вважати зручним включити "файл" конфігурації динамічно обчислюватися під час ініціалізації (звичайно, залишаючи тягар розумної конфігурації вашому системному адміністратору або користувачеві; насправді це конфігурація текст, який надходить з якогось файлу або з якоїсь команди). Для цього ви можете просто прийняти умовудокументувати її), що шлях конфігураційного файлу, що починається, наприклад, з a !або a, |є насправді командою оболонки, яку ви читали б як конвеєр . Це залишає користувачеві можливість вибору будь-якого «препроцесора» або «мови сценаріїв», з якої він найбільш знайомий.

(вам потрібно довіритися своєму користувачеві щодо проблем безпеки, якщо ви приймаєте динамічно обчислені конфігурації)

Тож у коді ініціалізації ви main(наприклад) приймете якийсь --config аргумент confarg і отримаєте FILE*configf;його з нього. Якщо цей аргумент починається з !(тобто, якщо (confarg[0]=='!')....), ви б використовували configf = popen(confarg+1, "r");та закривали цю трубку pclose(configf);. Інакше ви б використали configf=fopen(confarg, "r");та закрили цей файл за допомогою fclose(configf);(не забудьте перевірку помилок). Дивіться труба (7) , попен (3) , фопен (3) . Для програми, закодованої в Python, прочитайте про os.popen тощо.

(документ також для дивного користувача, який хоче передати файл конфігурації, іменований !foo.configдля передачі, ./!foo.configщоб обійти popenфокус вище)

До речі, такий трюк є лише зручністю (щоб не вимагати від досвідченого користувача, наприклад, кодувати якийсь скрипт оболонки для створення файлу конфігурації ). Якщо користувач хоче повідомити про будь-яку помилку, він повинен надіслати вам створений файл конфігурації ...

Зауважте, що ви також можете розробити свою програму з можливістю використання та завантаження плагінів під час ініціалізації, наприклад, з dlopen (3) (і вам потрібно довіряти своєму користувачеві про цей плагін). Знову ж таки, це дуже важливе архітектурне рішення (і вам потрібно визначити та надати деякі досить стабільні API та умови щодо цих плагінів та вашої програми).

Для додатки , закодоване в мові сценаріїв , як Python ви можете також прийняти деякі програми аргумент для Eval або Exec або подібних примітивів. Знову ж таки, питання безпеки викликають занепокоєння (просунутого) користувача.

Що стосується текстового формату вашого файлу конфігурації (генерується він чи ні), я вважаю, що в основному вам потрібно добре його документувати (а вибір якогось конкретного формату не так важливий; проте я рекомендую дозволити вашому користувачеві мати можливість розмістити дещо -сказано- коментарі всередині нього). Ви можете використовувати JSON (бажано, щоб якийсь аналізатор JSON приймав і пропускав коментарі звичайними //до eol або /*... */...), або YAML, або XML, або INI або власною справою. Розбирати файл конфігурації досить просто (і ви знайдете багато бібліотек, пов’язаних із цим завданням).


+1 для згадування про повну цінність мов програмування Тьюрінга. Деякі цікаві роботи показують, що обмеження обчислювальної потужності вхідного формату є ключовим для забезпечення вхідного шару обробки. Використання повної мови програмування Тьюрінга йде в зворотному напрямку.
Матей Морейра

2

Додаючи до відповіді Амона , чи розглядали ви альтернативи? JSON, можливо, більше, ніж вам потрібно, але файли Python, ймовірно, нададуть вам проблем у майбутньому з причин, зазначених вище.

Однак у Python вже є аналізатор конфігурації дуже простої мови конфігурації, який може відповідати всім вашим потребам. ConfigParserМодуль реалізує просту мову конфігурації.


1
Використання чогось "схожого на ... файли INI Microsoft Windows" здається поганою ідеєю, як на тій підставі, що це не особливо гнучкий формат, так і тому, що "подібне" означає недокументовану несумісність.
Піт Кіркхем,

1
@PeteKirkham Ну, це просто, це документально підтверджено і це частина стандартної бібліотеки Python. Це може бути ідеальним рішенням для потреб ОП, оскільки він шукає те, що підтримується безпосередньо Python і простіше, ніж JSON. Поки він далі не уточнює, які його потреби, я думаю, що ця відповідь може бути йому корисною.
CodeMonkey

1
Я збирався запропонувати по суті це - подивіться, які типи файлів конфігурації підтримують Python libs і виберіть один із них. Також, Powershell має поняття розділів даних - які дозволяють обмежено побудувати мову Powershell - захищаючи від шкідливого коду. Якщо Python має вкладку, яка підтримує обмежений підмножина Python для конфігурації, це принаймні пом'якшує один із мінусів проти ідеї в ОП.
Χpẘ

1
@PeteKirkham Це швидше навпаки, проблема. У Windows, як правило, є купа недокументованих лайна, яка вибухає на вас. Python має тенденцію бути добре зафіксованим та зрозумілим. Однак, якщо все, що вам потрібно, це прості пари ключ / значення ( можливо, з розділами), це досить вдалий вибір. Я підозрюю, що це охоплює 90% випадків використання. Якщо файли конфігурації .NET були ini замість жахливого XML зі схемою, яка насправді коду маскує як конфігурацію, нам би все було набагато краще.
jpmc26

1
@PeteKirkham Не дуже. INI, найкраще для простих випадків використання, швидше за все, ви можете уникнути будь-яких несумісностей. Вони також не мають значення, якщо ви не використовуєте файл двома різними мовами, і навіть якщо ви є, ви, ймовірно, можете знайти відкриті реалізації будь-якою мовою (що дозволяє або не мати несумісності, або, як мінімум, точно знати, що вони є). Я погоджуюся, що ви повинні використовувати інший формат, якщо ваш випадок використання насправді достатньо складний, щоб ви почали працювати з ними або якщо ви не можете знайти існуючу реалізацію, якій можна довіряти, але це не є загальним явищем.
jpmc26

1

Я довго працював з деяким відомим програмним забезпеченням, яке має свої конфігураційні файли, записані в TCL, тому ідея не нова. Це спрацювало непогано, оскільки користувачі, які не знали мови, все ще могли писати / редагувати прості файли конфігурації, використовуючи одне set name valueтвердження, тоді як більш просунуті користувачі та розробники могли використовувати для цього складні хитрощі.

Я не думаю, що "конфігураційні файли можуть бути важкими для налагодження" є вагомою проблемою. Поки ваша програма не змушує користувачів писати сценарії, ваші користувачі завжди можуть використовувати прості завдання у своїх конфігураційних файлах, що навряд чи складніше отримати в порівнянні з JSON або XML.

Переписання конфігурації є проблемою, хоча це не так вже й погано, як здається. Оновлення довільного коду неможливо, але завантаження конфігурації з файлу, зміна його та збереження назад є. В основному, якщо ви зробите деякі сценарії в конфігураційному файлі, який не є лише для читання, ви просто set name valueзбережете еквівалентний список операторів після його збереження. Хороший натяк, що це станеться, - коментар "не редагувати" на початку файлу.

Одне, що слід врахувати, - це те, що ваші конфігураційні файли не будуть надійно читати за допомогою простих інструментів, заснованих на регулярних виразках, таких як sed, але, наскільки я розумію, це вже не так у ваших поточних файлах JSON, тому втратити не багато.

Просто переконайтеся, що ви використовуєте відповідні методи пісочниці під час виконання своїх конфігураційних файлів.


1
"Програмне забезпечення" є незлічуваним іменником, тому воно повинно бути " деяким відомим програмним забезпеченням".
jpmc26

1

Окрім усіх вагомих моментів інших хороших відповідей тут (ух, вони навіть згадували про концепцію повного Тюрінга), насправді є ще кілька вагомих практичних причин НЕ використовувати файл Python як свою конфігурацію, навіть коли ви працюєте на Python- тільки проект.

  1. Налаштування всередині вихідного файлу Python технічно є частиною виконуваного вихідного коду, а не файлу даних лише для читання. Якщо ви йдете цим маршрутом, то, як правило, це робите import config, оскільки саме така «зручність», мабуть, була однією з головних причин того, що люди почали користуватися файлом Python як конфігурацією в першу чергу. Тепер ви схильні зафіксувати цю config.py у вашій репо, інакше ваш кінцевий користувач зіткнеться з заплутаним ImportError при першому спробі запустити вашу програму.

  2. Якщо припустити, що ви фактично зробили цю config.py у вашій репо, тепер члени вашої команди, ймовірно, мають різні налаштування в різних умовах. Уявіть, що колись якийсь член випадково передає свій локальний файл конфігурації в репо.

  3. І останнє, але не менш важливе, ваш проект може мати паролі у файлі конфігурації. (Це сама по собі дискусійна практика, але вона все-таки трапляється.) І якщо ваш файл конфігурації існує в репо, ви ризикуєте скористатися вашим обліковим записом публічним репо.

Тепер, використовуючи файл конфігурації лише для даних, наприклад універсальний формат JSON, можна уникнути всіх трьох вищезазначених проблем, оскільки ви можете розумно попросити користувача створити власний config.json і подати його у вашу програму.

PS: Це правда, що JSON має багато обмежень. 2 обмежень, згаданих ОП, можна вирішити творчістю.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.