Захотелось тут на днях написать небольшую утилиту на python, дабы пользу себе нанести и язык заодно вспомнить. И оказалось, что требует она для своей работы конфиг. В мозгу сразу возникли слова: json, ini, xml, yaml и т.п. Но вот незадача - кто-то из них в стандартной библиотеке python отсутствует, где-то комментарии не поддерживаются, что-то имеет ужасный интерфейс работы из под python, опять же произвольную вложенность не везде можно использовать. И в добавок абсолютно все не поддерживают типизацию. Я уж было совсем приуныл, но в этот момент постучалась в мою голову одна светлая мысль: а python ведь скриптовый язык.
Действительно, что может быть проще - пишем конфиг на python, с его прекрасным синтаксисом, который решает все вышеперечисленные проблемы, а загрузить и распарсить его потом - проще, чем ini файл.
Вот допустим есть у нас вот такой конфиг:
Грузится он всего в 2 строчки:
Вуаля в словаре config_data, мы получаем все глобальные переменные из конфига, доступаться к ним можно по имени переменной. Типизация сохранена, произвольная вложенность, комменты, и главное использовать - проще некуда. Есть правда одна особенность, такой конфиг будет исполняемым, что делает его не совсем безопасным. Но если вы его пишете сами, а не качаете с сомнительных ресурсов - это даже скорее плюс, а не минус, гибкости добавляет такой, что никаким декларативным форматам и не снилось.
P.S.: Пример этот на 3-м питоне, для 2-го по моему синтаксис загрузки чуточку другой, но все так же делается в 2 строчки.
P.P.S.: Судя по комментариям не понятно, что: в config_path - можно передать полный путь к конфигу, без добавления его в sys.path. А для перечитывания конфига достаточно вызывать строчку с exec еще один раз, никаких reload делать не нужно.
Действительно, что может быть проще - пишем конфиг на python, с его прекрасным синтаксисом, который решает все вышеперечисленные проблемы, а загрузить и распарсить его потом - проще, чем ini файл.
Вот допустим есть у нас вот такой конфиг:
param1 = ["a", "b"] param2 = 3 + 5
config_data = {} exec(open(config_path).read(), config_data) print(config_data["param1"]) print(config_data["param2"])
P.S.: Пример этот на 3-м питоне, для 2-го по моему синтаксис загрузки чуточку другой, но все так же делается в 2 строчки.
P.P.S.: Судя по комментариям не понятно, что: в config_path - можно передать полный путь к конфигу, без добавления его в sys.path. А для перечитывания конфига достаточно вызывать строчку с exec еще один раз, никаких reload делать не нужно.
А чем обычный import этого модуля плох?
ОтветитьУдалить- загрязняем область видимости нашего приложения
Удалить- импорт файла, который лежит не рядом со скриптом, а в произвольной папке - не так просто сделать
- перечитать такой файл без перезагрузки приложения тоже не совсем тривиально
1. решается через alias
Удалить2. ну совсем произвольная редно используется, но согласен.
3. reload (module) имеет грабли?
По моему были какие-то особенности у reload, но не суть, тебе правда легче написать что-то вроде:
Удалитьimport sys
import importlib
sys.path.insert(0, '/path/to/config')
import config
importlib.reload(config)
вместо тех 2 строк? В любом случае смысл поста в том, что использовать python скрипт в качестве конфига, в большинстве случаев удобнее чем json, xml и т.п.
ты как обычно усложняешь примеры из ответов и не усложняешь свои ;)
УдалитьВ твоем примере нет ни другой директории, ни перечитывания конфига ;) Поэтому зря ты написал про свои "2 строчки"
Но суть того, что конфиг для питона действительно интересно делать на питоне, это не меняет.
Хотя это означает, что человек редактирующий твой "питон"-конфиг должен знать синтаксис питона. Не факт что он сложнее тех же xml или json, но последние более популярней и привычней.
Вот уж не думал, что тебя так заденет. Но ты напраслину возводишь, в моем примере работает примерно вот так:
Удалитьdef config():
config_data = {}
exec(open("/home/rean/projects/git/py-pacman-manager/config.py").read(), config_data)
return config_data
т.е. я могу указать полный путь к конфигу, без модификации sys.path, я могу вызвать функцию config второй раз и получу текущий конфиг, каждый вызов всегда заново его перечитывает.
Добавил это в пост, возможно действительно не очевидно )
Удалить