Если вы часто пишете что-то на python — необязательно даже какие-то большие проекты, просто какие админские утилиты под себя, — то рано или поздно придется задуматься о хранении настроек вашего приложения/скрипта.Конечно для совсем небольшого скрипта многие просто делают кортеж типа «опция»-«значение», сбрасывают его в простой текстовый файл и потом с ним как-то работают.Очевидно, что это подходит для скриптов, которые будут поддерживаться со временем.
Кроме того в силу своей гибкости python позволяет создать файл вроде settings.py и исполнять его на уровне кода.
То есть просто сделать settings.py таким :
import os.path as path
conf_path = path.join(path.dirname(__file__), "config")
my_settings = {
'item 1' : "value 1",
'item 2' : "value 2",
...
}
А потом его импортировать и как-то работать :
import settings
...
def main():
...
print settings.conf_path
...
Но какждый раз лезть в settings.py и менять там какие-то опции это явно не комильфо.Следует ,как мне кажется, максмимально разделять логику и настройки.
Человечество уже давно придумало такую штуку, как XML. Существует огромное число библиотек для работы с XML и python-биндингов к ним. Несложно сериализовать обьекты в XML. Очень много софта используют XML для хранения настроек. Самый близкий пример — plist файлы в Mac OS/iOS и т.д.
Но мне кажется есть как минимум один недостаток (кроме производительности) — такой конфиг как неудобно редактировать руками человеку.Смотреть на портянку тегов как-то не очень.
Поэтому есть компромисс между XML и простыми текстовыми настройками — это так называемые .conf файлы, использумые широко в *nix/linux софте. Например, smb.conf для настроек сервера samba :
Синтаксис такого файла прост : он состоит из одного или более именованных разделов, каждый из которых может содержать отдельные параметры с именами и значениями.Разделом являются строки, начинающиеся с «[» и заканчивающиеся на «]«. Значение в квадратных скобках — название раздела, и может содержать любые символы, кроме квадратных скобок.
Простой пример :
[database_connection] dbtype = mysql url = http://localhost:3306 username = admin password = admin_password
Сохраним на вымышленный конфиг подключения к серверу БД как dbconnect.conf.
Теперь каким образом без ручного считывания и парсинга этого файла сделать класс аля Settings? Да все просто. Уже написан отличный модуль ConfigParser, о котором собственно весь пост. Ставим этот модуль при помощи easy_install :
sudo easy_install ConfigParser
Или при помощи pip. В моей K/Ubuntu 11.10 для python 2.7 он уже установлен.И так, пилим класс (пусть будет в отдельном файле MyBDConfig.py):
from ConfigParser import SafeConfigParser
class BDProperties:
def __init__(self, fname):
self.filename = fname;
self.cfgParser = SafeConfigParser();
def load(self):
self.cfgParser.read(self.filename);
def getDBType(self):
return self.cfgParser.get('database_connection','dbtype');
def getURL(self):
return self.cfgParser.get('database_connection','url');
def getLogin(self):
return self.cfgParser.get('database_connection','username');
def getPass(self):
return self.cfgParser.get('database_connection','password');
Итак, здесь мы импортировали необходимый нам модуль ConfigParser и использовали класс SafeConfigParser.Собственно после инициализации мы считываем наш конфиг-файл методом read(), который может принимать несколько путей к файлам и для каждого из них создать объект типа SafeConfigParser.
Для доступа к опции значению опции «op» секции «section» используем вызов метода get(«section»,»op»), как здесь :
...
def getDBType(self):
return self.cfgParser.get('database_connection','dbtype');
...
Проверяем — я для этого использую чумовую штуку под названием ipython :
Всё ок.Вот таким нехитрым способом можно считывать конфиги.read () возвращает список, содержащий имена файлов, успешно загруженных , чтобы ваше приложение могло определить, каких файлов конфигурации не хватает, и решить, следует ли игнорировать их.
Модуль легко подружить с юникодовыми конфигами, используя codecs.
С помощью этого модуля можно лекго пробежаться по структуре всего конфига, например так :
from ConfigParser import SafeConfigParser
parser = SafeConfigParser()
parser.read('/home/teddy/config/dbconnect.conf')
for section_name in parser.sections():
print 'Section:', section_name
print ' Options:', parser.options(section_name)
for name, value in parser.items(section_name):
print ' %s = %s' % (name, value)
Что даст :
teddy@teddy-System-Product-Name:~/config$ python explore.py Section: database_connection Options: ['dbtype', 'url', 'username', 'password'] dbtype = mysql url = http://localhost:3306 username = admin password = admin_password teddy@teddy-System-Product-Name:~/config$
В качестве разделителя опции и её значения можно использовать как «=«, так и «:«.
Остается лишь понять, как модифицировать наш конфиг. Для того чтобы модифицировать значение «value» опции «option» в секции «section» нужно сделать так :
...
ConfigParser.set('section','option','value');
...
Создать новый файл конфигурации что называется «from scratch» тоже легко :
import sys,ConfigParser
parser = ConfigParser.SafeConfigParser()
config_file = open("/home/teddy/config/new_config.conf","w")
parser.add_section('section 1')
parser.set('section 1', 'option 1', 'val 1')
parser.set('section 1', 'option 2', 'val 2')
for section in parser.sections():
print section
for name, value in parser.items(section):
print ' %s = %r' % (name, value)
parser.write(config_file)
Как видим, был создан требуемый файл конфигурации :
Собственно, для того чтобы начать правильно хранить конфиги ваших приложений на python, этого достаточно.За бортом остались вопросы валидации, интерполяции значений и DEFAULT секции.Все это есть здесь :


