Рубрики
Без рубрики

Configobj + счастье

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Я недавно начал использовать Майкл Фод Configobj Для одного из наших внутренних wxpython Приложения на работе. Когда я написал мою другую конфигурацию Учебное пособие Я хотел показать вам, как я использовал configobj с помощью моих предпочтений диалоговом окна, но я не хотел, чтобы все мои посты включили WX. В этой статье я просто покажу вам, насколько легко добавить новую настройку предпочтений в Configobj, не вытирая свои оригинальные и как загрузить и сохранить их с диалоговым окном WXPYPHON. Теперь давайте доберемся до этого!

Сначала мы создадим простой контроллер для создания и доступа к нашему файлу конфигурации с помощью Configure:

import configobj
import os
import sys
import wx
from wx.lib.buttons import GenBitmapTextButton

appPath = os.path.abspath(os.path.dirname(os.path.join(sys.argv[0])))
inifile = os.path.join(appPath, "example.ini")

########################################################################
class CloseBtn(GenBitmapTextButton):
    """
    Creates a reusuable close button with a bitmap
    """

    #----------------------------------------------------------------------
    def __init__(self, parent, label="Close"):
        """Constructor"""
        font = wx.Font(16, wx.SWISS, wx.NORMAL, wx.BOLD)
        img = wx.Bitmap(r"%s\images\cancel.png" % appPath)
        GenBitmapTextButton.__init__(self, parent, wx.ID_CLOSE, img, 
                                     label=label, size=(110, 50))
        self.SetFont(font)

#----------------------------------------------------------------------
def createConfig():
    """
    Create the configuration file
    """
    config = configobj.ConfigObj()
    config.filename = inifile
    config['update server'] = "http://www.someCoolWebsite/hackery.php"    
    config['username'] = ""
    config['password'] = ""
    config['update interval'] = 2
    config['agency filter'] = 'include'
    config['filters'] = ""
    config.write()
    
#----------------------------------------------------------------------
def getConfig():
    """
    Open the config file and return a configobj
    """
    if not os.path.exists(inifile):
        createConfig()
    return configobj.ConfigObj(inifile)

Этот кусок кода довольно прост. В CreateConfig Функция, она создает файл «example.ini» в том же каталоге, как тот, от которого работает этот скрипт. Файл конфигурации получает шесть полей, но не разделы. В getconfig Функция, код проверки для существования файла конфигурации и создает его, если оно не существует. Независимо от того, функция возвращает объект configobj к абонеру. Мы поставим этот скрипт в «Controller.py». Теперь мы подклассьте класс WX.Dialog для создания диалогового окна предпочтений.

# -----------------------------------------------------------
# preferencesDlg.py
#
# Created 10/20/2009 by mld
# -----------------------------------------------------------

import controller
import wx
from wx.lib.buttons import GenBitmapTextButton

########################################################################
class PreferencesDialog(wx.Dialog):
    """
    Creates and displays a preferences dialog that allows the user to
    change some settings.
    """

    #----------------------------------------------------------------------
    def __init__(self):
        """
        """
        wx.Dialog.__init__(self, None, wx.ID_ANY, 'Preferences', size=(550,300))
        appPath = controller.appPath
        
        # ---------------------------------------------------------------------
        # Create widgets
        font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
        serverLbl = wx.StaticText(self, wx.ID_ANY, "Update Server:")
        self.serverTxt = wx.TextCtrl(self, wx.ID_ANY, "")
        self.serverTxt.Disable()
        
        usernameLbl = wx.StaticText(self, wx.ID_ANY, "Username:")
        self.usernameTxt = wx.TextCtrl(self, wx.ID_ANY, "")
        self.usernameTxt.Disable()
        
        passwordLbl = wx.StaticText(self, wx.ID_ANY, "Password:")
        self.passwordTxt = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PASSWORD)
        self.passwordTxt.Disable()
        
        updateLbl = wx.StaticText(self, wx.ID_ANY, "Update Interval:")
        self.updateTxt = wx.TextCtrl(self, wx.ID_ANY, "")
        minutesLbl = wx.StaticText(self, wx.ID_ANY, "minutes")
        
        agencyLbl = wx.StaticText(self, wx.ID_ANY, "Agency Filter:")
        choices = ["Include all agencies except", "Exclude all agencies except"]
        self.agencyCbo = wx.ComboBox(self, wx.ID_ANY, "Include all agencies except",
                                     None, wx.DefaultSize, choices, wx.CB_DROPDOWN|wx.CB_READONLY)
        self.agencyCbo.SetFont(font)
        self.filterTxt = wx.TextCtrl(self, wx.ID_ANY, "")
        
        img = wx.Bitmap(r"%s/images/filesave.png" % appPath)
        saveBtn = GenBitmapTextButton(self, wx.ID_ANY, img, "Save", size=(110, 50))
        saveBtn.Bind(wx.EVT_BUTTON, self.savePreferences)
        cancelBtn = controller.CloseBtn(self, label="Cancel")
        cancelBtn.Bind(wx.EVT_BUTTON, self.onCancel)
        
        widgets = [serverLbl, usernameLbl, passwordLbl, updateLbl, agencyLbl, minutesLbl,
                   self.serverTxt, self.usernameTxt, self.passwordTxt, self.updateTxt,
                   self.agencyCbo, self.filterTxt, saveBtn, cancelBtn]
        for widget in widgets:
            widget.SetFont(font)
        
        # ---------------------------------------------------------------------
        # layout widgets
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        updateSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        prefSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
        prefSizer.AddGrowableCol(1)
        
        prefSizer.Add(serverLbl, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
        prefSizer.Add(self.serverTxt, 0, wx.EXPAND)
        prefSizer.Add(usernameLbl, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
        prefSizer.Add(self.usernameTxt, 0, wx.EXPAND)
        prefSizer.Add(passwordLbl, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
        prefSizer.Add(self.passwordTxt, 0, wx.EXPAND)
        prefSizer.Add(updateLbl, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
        updateSizer.Add(self.updateTxt, 0, wx.RIGHT, 5)
        updateSizer.Add(minutesLbl, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
        prefSizer.Add(updateSizer)
        prefSizer.Add(agencyLbl, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
        prefSizer.Add(self.agencyCbo, 0, wx.EXPAND)
        prefSizer.Add((20,20))
        prefSizer.Add(self.filterTxt, 0, wx.EXPAND)
        
        mainSizer.Add(prefSizer, 0, wx.EXPAND|wx.ALL, 5)
        btnSizer.Add(saveBtn, 0, wx.ALL, 5)
        btnSizer.Add(cancelBtn, 0, wx.ALL, 5)
        mainSizer.Add(btnSizer, 0, wx.ALL | wx.ALIGN_RIGHT, 10)
        self.SetSizer(mainSizer)
                
        # ---------------------------------------------------------------------
        # load preferences
        self.loadPreferences()
        
    #----------------------------------------------------------------------
    def loadPreferences(self):
        """
        Load the preferences and fill the text controls
        """
        config = controller.getConfig()
        updateServer = config['update server']
        username = config['username']
        password = config['password']
        interval = config['update interval']
        agencyFilter = config['agency filter']
        filters = config['filters']
        
        self.serverTxt.SetValue(updateServer)
        self.usernameTxt.SetValue(username)
        self.passwordTxt.SetValue(password)
        self.updateTxt.SetValue(interval)
        self.agencyCbo.SetValue(agencyFilter)
        self.filterTxt.SetValue(filters)
        
    #----------------------------------------------------------------------
    def onCancel(self, event):
        """
        Closes the dialog
        """
        self.EndModal(0)
        
    #----------------------------------------------------------------------
    def savePreferences(self, event):
        """
        Save the preferences
        """
        config = controller.getConfig()
        
        config['update interval'] = self.updateTxt.GetValue()
        config['agency filter'] = str(self.agencyCbo.GetValue())
        data = self.filterTxt.GetValue()
        if "," in data:
            filters = [i.strip() for i in data.split(',')]
        elif " " in data:
            filters = [i.strip() for i in data.split(' ')]
        else:
            filters = [data]
        text = ""
        for f in filters:
            text += " " + f
        text = text.strip()
        config['filters'] = text
        config.write()
        
        dlg = wx.MessageDialog(self, "Preferences Saved!", 'Information',  
                               wx.OK|wx.ICON_INFORMATION)
        dlg.ShowModal()        
        self.EndModal(0)
        
if __name__ == "__main__":
    app = wx.PySimpleApp()
    dlg = PreferencesDialog()
    dlg.ShowModal()
    dlg.Destroy()

Вышеуказанный код создает диалоговое окно основных предпочтений и загружает свою конфигурацию из файла с помощью ConfigObj. Вы можете увидеть, как это работает, читая код в LeadPreferences метод. Единственный другой кусок, о котором мы заботимся о том, как код сохраняет настройки, когда пользователь их изменяет. Для этого нам нужно посмотреть на SavePreferences метод. Это довольно простой метод, в том, что все, что он делает, это захватывает различные значения из виджетов с использованием определенных функций PETTER WX. Есть также условный, который имеет небольшую проверку на поле фильтра. Основная причина того, что в моей оригинальной программе я использую пространство в качестве разделителя и программу, необходимую для конвертации запятых и таких пробелов. Этот код все еще работает в процессе, хотя, поскольку она не охватывает все случаи, которые могут войти пользователь.

В любом случае, как только у нас есть значения внутри интерфейса Configobj, подобной Dict, мы пишем данные Configobj экземпляра в файл. Затем программа отображает простой диалог, чтобы пользователь узнал, что сохраняется.

Теперь скажем, что спецификации нашей программы изменяются так, что нам нужно добавить или удалить предпочтение. Все, что требуется для этого, это добавить или удалить его в файл конфигурации. Configobj заберет изменения, и нам просто нужно помнить, чтобы добавить или удалить соответствующие виджеты в нашем графическом интерфейсе. Одна из лучших вещей в Configobj заключается в том, что он не будет сбрасывать данные в ваш файл, он просто добавит изменения в зависимости от необходимости. Дайте это попробовать и узнать, насколько это легко!

ПРИМЕЧАНИЕ. Вся код протестирован на Windows XP с Python 2.5, ConfigObj 4.6.0 и Validate 1.0.0.

Загрузки

  • ConfigObj-GUI-Ex.zip
  • Configobj-gui-ex.tar