Насколько плоха идея использовать файлы Python в качестве файлов конфигурации?

72

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

Я видел, как Celery использует реальные файлы Python для конфигурации. Первоначально я скептически относился к этому. Но идея использования простых структур данных Python для конфигурирования начинает развиваться. Некоторые плюсы:

  • Структуры данных будут такими же, как я обычно кодирую. Поэтому мне не нужно менять настроение.
  • Моя IDE (PyCharm) понимает связь между конфигурацией и кодом. Ctrl+ Bпозволяет легко переключаться между конфигурацией и кодом.
  • Мне не нужно работать с IMO ненужным строгим 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 смогут.
Йорг Миттаг
3
@ JörgWMittag Туринская комплектность не означает, что можно отправлять сообщения по сети или получать доступ к жесткому диску. То есть Туринская комплектность - это обработка, а не ввод-вывод. Например, CSS считается полностью готовым в Турине, но он не будет портить ваше постоянное хранилище. В другом месте вы сказали, что «Идрис является полностью чистым функциональным языком, так что он по определению не является полным по Тьюрингу», что не следует, и, по-видимому, это полный Турин. Я был убежден, что использование Testris-complete означает, что язык был законченным в Турине, но не в состоянии выполнить полный ввод-вывод ... кажется, это не то, что вы имеете в виду.
Theraot
6
@Theraot: «Всего» означает, что он всегда возвращается. Машина Тьюринга может выполнять бесконечный цикл, то есть она может не возвращаться. Следовательно, Идрис не может делать все, что делает машина Тьюринга, а значит, она не является полной по Тьюрингу. Это верно для всех языков с зависимой типизацией. Весь смысл языка с зависимой типизацией заключается в том, что вы можете выбирать произвольные свойства для программ, тогда как на языке, полном Тьюринга, вы даже не можете определять тривиальные свойства, такие как «останавливает ли эта программа?» Тотальные языки по определению не являются полными по Тьюрингу, потому что машины Тьюринга являются частичными.
Йорг Миттаг
10
Определение из «Тьюринга» является «может реализовать Тьюринг машин». Определение «Tetris-complete» - это «можно реализовать Tetris». Весь смысл этого определения в том, что полнота по Тьюрингу просто не очень интересна в реальном мире. Существует множество полезных языков, которые не являются полными по Тьюрингу, например, HTML, SQL (до 1999 года), различные DSL и т. Д. OTOH, полнота по Тьюрингу только подразумевает, что вы можете вычислять функции по натуральным числам, это не означает, что печать на экране, доступ к сети, взаимодействие с пользователем, ОС, средой, все это важно.
Йорг Миттаг
4
Причина, по которой Эдвин Брэди использовал этот пример, заключается в том, что многие думают, что языки, не полные по Тьюрингу, не могут использоваться для программирования общего назначения. Я и раньше думал, что тоже, поскольку, в конце концов, многие интересные программы представляют собой бесконечные циклы, которые мы не хотим останавливать , например, серверы, операционные системы, циклы событий в графическом интерфейсе, игровые циклы. Многие программы обрабатывают бесконечные данные, например, потоки событий. Раньше я думал, что вы не можете написать это на общем языке, но с тех пор я узнал, что вы можете , и поэтому я считаю хорошей идеей иметь термин для этой возможности.
Йорг Миттаг
50

+1 ко всему в ответе амона . Я хотел бы добавить это:

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

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

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

РЕДАКТИРОВАТЬ для записи: несколько человек прокомментировали этот ответ о том, насколько вероятно или маловероятно, что проект когда-либо будет успешно полностью переписан на другом языке. Справедливо сказать, что полное обратно-совместимое переписывание, вероятно, встречается редко. На самом деле я имел в виду фрагменты одного и того же проекта (и нуждающегося в доступе к одной и той же конфигурации), написанные на разных языках. Например, обслуживающий стек в C ++ для скорости, пакетная очистка базы данных в Python, некоторые сценарии оболочки в качестве клея. Так что подумайте и об этом тоже :)

Celada
источник
1
@ Маст, извиняюсь, но я не следую. Имя файла (независимо от того, заканчивается ли оно на .py) ни здесь, ни там. Я пытаюсь подчеркнуть, что если он написан на Python, вам нужен интерпретатор Python для его чтения.
Селада
12
@ Думаю, ты неправильно это делаешь. Идея, которую я взял из этого ответа (как оригинального, так и отредактированного), заключается в том, что при написании файлов конфигурации на языке программирования затрудняется написание кода на другом языке. Например, вы решили портировать свое приложение на Anrdoid / iPhone и будете использовать другой язык. Вы должны (а) положиться на интерпретатор Python в приложении для мобильного телефона (не идеально), (б) переписать конфигурацию в не зависящем от языка формате и переписать код Python, который ее использовал, или (в) сохранить два формата конфигурации в будущем.
Джон Бентли
4
@JonBentley Я полагаю, что беспокойство будет актуально, если планируется создание многоязычных проектов. Я не получил такое впечатление от ОП. Кроме того, использование текстовых файлов для конфигурации все еще требует дополнительного кода (на всех языках) для фактического анализа / преобразования значений. Технически, если они ограничивают сторону Python key=valueприсвоениями для config, я не понимаю, почему программа на Java / C ++ не может прочитать файл Python как обычный текстовый файл и проанализировать его так же, если им нужно перейти к чему-то другому в будущее. Я не вижу необходимости в полноценном интерпретаторе Python.
code_dredd
3
@ray Верно, но ответ все еще полезен на том основании, что вопросы не должны быть применимы только к человеку, который их публикует. Если вы используете стандартизированный формат (например, INI, JSON, YAML, XML и т. Д.), То, скорее всего, вы будете использовать существующую библиотеку анализа, а не писать свою собственную. Это сокращает дополнительную работу до просто класса адаптера для взаимодействия с библиотекой синтаксического анализа. Если вы ограничиваете себя ключом = значением, то это устраняет большинство причин ОП, чтобы в первую очередь использовать Python, и вы могли бы просто пойти в признанном формате.
Джон Бентли
3
Я должен был сделать это несколько лет назад, когда инструмент, написанный на Lua, использовал скрипт Lua в качестве своих конфигов, затем они хотели, чтобы мы написали новый инструмент на C #, и специально попросили нас использовать скрипт конфигурации Lua. У них было всего 2 строки, которые на самом деле были программируемыми, а не простыми x = y, но мне все равно пришлось узнать о интерпретаторах Lua с открытым исходным кодом для .net из-за них. Это не чисто теоретический аргумент.
Кевин Фее
21

Другие ответы уже очень хороши, я просто привожу свой опыт использования в реальных проектах в нескольких проектах.

Pros

Они в основном уже прописаны:

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

Cons

  • злоумышленники могут делать все, что может делать ваша основная программа; Я не считаю это большой проблемой, так как обычно, если пользователь может изменить файл конфигурации, он / она уже может делать все, что может делать приложение;
  • если вы больше не участвуете в программе на 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 для конфигурации, отредактированный из пользовательского интерфейса.

Matteo Italia
источник
1
очень хороший момент о создании или переписывании конфигурации! Но немногие форматы, кроме XML, могут сохранять комментарии в выводе, что я считаю чрезвычайно важным для конфигурации. Другие форматы иногда вводят note:поле, которое игнорируется для конфигурации.
Амон
2
«если пользователь может изменить файл конфигурации, он / она уже может делать все, что может делать приложение» - это не совсем так. Как насчет тестирования, чем блестящего конфигурационного файла, который вы не знаете, загрузили на pastebin?
Дмитрий Григорьев
2
@DmitryGrigoryev: если вы стремитесь к этой цели, вы можете также сказать своей жертве скопировать и вставить ее curl ... | bash, это еще меньше хлопот. :-P
Matteo Italia
@DmitryGrigoryev: и это тот тип вещей, который может позволить кому-то полностью разрушить производственную систему в первый же день работы. Если 'eval' является вашим анализатором, это означает, что нет возможности проверить его на наличие проблем до того, как он будет прочитан. (та же самая причина, по которой скрипты оболочки так плохо работают). INI, YAML или JSON безопасны в этом отношении.
Джо
1
@DmitryGrigoryev: я просто хочу сказать, что если ваш тип жертвы достаточно глуп, чтобы слепо копировать и вставлять файл конфигурации, вы, вероятно, можете заставить его / ее делать что-либо на своей машине с помощью менее косых методов («вставьте это в консоль, чтобы исправь свою проблему! "). Кроме того, даже с неисполняемыми файлами конфигурации существует большой риск причинения вреда - даже просто злонамеренно указав ведение журнала над критическими файлами (если приложение работает с достаточными правами), вы можете нанести ущерб системе. Вот почему я думаю, что на практике это не так уж много различий с точки зрения безопасности.
Маттео Италия
8

Главный вопрос: хотите ли вы, чтобы ваш файл конфигурации был на каком-то полном языке Тьюринга (как, например, Python)? Если вы этого хотите, вы можете также рассмотреть возможность встраивания какого-либо другого языка сценариев (полный по Тьюрингу), такого как Guile или Lua (потому что он может восприниматься как «более простой» для использования или встраивания, чем Python; прочитайте главу о расширении и Встраивание Python ). Я не буду обсуждать это дальше (потому что другие ответы - например, Amon - подробно обсуждали это), но обратите внимание, что встраивание языка сценариев в ваше приложение является основным архитектурным выбором , который вы должны рассмотреть очень рано; Я действительно не рекомендую делать этот выбор позже!

Хорошо известным примером программы, настраиваемой с помощью «сценариев», является редактор emacs GNU (или, возможно, 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) , popen (3) , fopen (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Модуль реализует простой язык конфигурации.

CodeMonkey
источник
1
Использование чего-то «похожего на ... INI-файлы Microsoft Windows» кажется плохой идеей как на том основании, что это не очень гибкий формат, так и на том, что «подобное» подразумевает недокументированную несовместимость.
Пит
1
@PeteKirkham Ну, это просто, это задокументировано и является частью стандартной библиотеки Python. Это может быть идеальным решением для нужд OP, потому что он ищет что-то, что напрямую поддерживается Python и проще, чем JSON. Пока он не уточняет, что ему нужно, я думаю, что этот ответ может быть ему полезен.
CodeMonkey
1
Я собирался по существу предложить это - посмотрите, какие типы конфигурационных файлов поддерживают библиотеки Python, и выберите один из них. Кроме того, в Powershell есть понятие разделов данных, которые допускают ограниченные языковые конструкции Powershell, для защиты от вредоносного кода. Если у Python есть библиотека, которая поддерживает ограниченное подмножество Python для конфигурации, это как минимум смягчает одно из минусов против идеи в OP.
ẘpẘ
1
@PeteKirkham Скорее проблема наоборот. В Windows есть куча недокументированного дерьма, которое взрывает вас. Python, как правило, хорошо документирован и прост. Тем не менее, если вам все, что вам нужно, это простые пары ключ / значение ( возможно, с разделами), это довольно хороший выбор. Я подозреваю, что это покрывает 90% случаев использования. Если бы файлы конфигурации .NET были ini, а не чудовищным XML со схемой, которая фактически маскировала код под config, мы все были бы намного лучше.
jpmc26
1
@PeteKirkham Не совсем. INI лучше всего подходит для простых случаев использования, скорее всего, вы можете избежать любых несовместимостей. Они также не имеют значения, если вы не используете файл на двух разных языках, и даже если это так, вы, вероятно, можете найти открытые реализации на любом языке (что позволит вам либо не иметь несовместимости, либо, по крайней мере, точно знать, что они есть). Я согласен с тем, что вам следует использовать другой формат, если ваш вариант использования на самом деле достаточно сложен, чтобы вы начали сталкиваться с ним или если вы не можете найти существующую реализацию, которой можете доверять, но это не распространено.
jpmc26
1

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

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

Переписать конфиг - это проблема, хотя и не так плохо, как кажется. Обновление произвольного кода невозможно, но загрузка конфигурации из файла, его изменение и сохранение обратно. По сути, если вы выполняете некоторые скрипты в конфигурационном файле, который не предназначен только для чтения, вы просто получите эквивалентный список set name valueоператоров после его сохранения. Хороший намек на то, что это произойдет, - это комментарий «не редактировать» в начале файла.

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

Просто убедитесь, что вы используете соответствующие методы песочницы при выполнении ваших файлов конфигурации.

Дмитрий Григорьев
источник
1
«Программное обеспечение» несчетное существительное, поэтому оно должно быть « некоторые хорошо известным программным обеспечением.»
jpmc26
1

Помимо всех правильных моментов других хороших ответов здесь (вау, они даже упомянули концепцию Turing-complete), на самом деле есть пара веских практических причин НЕ использовать файл Python в качестве конфигурации, даже когда вы работаете над Python. единственный проект.

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

  2. Предполагая, что вы на самом деле фиксируете этот config.py в своем репо, теперь члены вашей команды, вероятно, будут иметь разные настройки в другой среде. Представьте себе, что когда-нибудь какой-нибудь участник случайно поместит свой локальный файл конфигурации в репозиторий.

  3. Наконец, что не менее важно, ваш проект может иметь пароли в файле конфигурации. (Это дискуссионная практика сама по себе, но в любом случае это происходит.) И если ваш файл конфигурации существует в репо, вы рискуете передать свои учетные данные в публичное репо.

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

PS: это правда, что JSON имеет много ограничений. 2 из ограничений, упомянутых ОП, могут быть решены с помощью некоторой креативности.

RayLuo
источник