[Python] Библиотека для работы с реестром Windows
От: Critical Error ICQ: 123736611
Дата: 30.09.09 05:11
Оценка: 36 (5)
Думаю многие windows-программеры, работающие с реестром натыкались на жутко неудобный api. Во многих проектах имеются всяческие обертки над этими апи, чтобы хоть както упростить работу. Python не исключение, так как стандартная библиотека _winreg представляет из себя простую обертку над функциями winapi.

Данная библиотека значительно облегчает работу с реестром, скрывая все тонкости winapi под простым и понятным интерфейсом.

Клас предоставляет 3 способа для доступа к реестру.

Стиль мэппинга:
Winreg(HKEY_CURRENT_USER)['SOFTWARE']['RegTest']['TestInt'] = 10

Стиль классов:
Winreg(HKEY_CURRENT_USER).SOFTWARE.RegTest.TestInt = 10

Или простой строкой:
Winreg(HKEY_CURRENT_USER, 'SOFTWARE\\RegTest\\TestInt') = 10
Winreg(HKEY_CURRENT_USER)['SOFTWARE\\RegTest\\TestInt'] = 10


Чтобы перечислить все секции в ветке используем функцию keys, возврящающую итератор по подключам:
for i in keys(t.SOFTWARE.RegTest):
    print repr(i)


Чтобы перечислить все значения в ветке используем функцию values, возврящающую итератор по парам (имя, значение):
for name,value in values(t.SOFTWARE.RegTest.test1):
    print name, value


Вот и все, пользуйтесь на здоровье.

Вот еще несколько примернов работы:
from winreg import *

# set test ====================================
>>> t = Winreg(HKEY_CURRENT_USER)
>>> t.SOFTWARE.RegTest = {} #< creats empty section
>>> t.SOFTWARE.RegTest.TestString = u'TestString'
>>> t.SOFTWARE.RegTest.TestInt = 10
>>> t.SOFTWARE.RegTest.test1.value1 = u'val1'
>>> t.SOFTWARE.RegTest.test1.value2 = 1
>>> t.SOFTWARE.RegTest.test1.value3 = 2
>>> t.SOFTWARE.RegTest.test2 = {}
>>> t.SOFTWARE.RegTest.test3 = {}
>>> t.SOFTWARE.RegTest2.TestString = u'TestString'
>>> t.SOFTWARE.RegTest2.location = 1

# get test ====================================
# map-style
>>> int(t['SOFTWARE']['RegTest']['TestInt'])
10

# class-style
>>> str(t.SOFTWARE.RegTest.TestString)
'TestString'

# folder-style
>>> str(t['SOFTWARE\\RegTest\\TestString'])
'TestString'

# coerce test
>>> v = t.SOFTWARE.RegTest.TestInt
>>> 1+v, v+1, int(v)
(11, 11, 10)

# exceptions =============================
>>> try:
...    print t.SOFTWARE.RegTest.test4
... except WindowsError, e:
...    print e
[Error 2] Value not found: Winreg(winreg.HKEY_CURRENT_USER, r"SOFTWARE\\RegTest\\test4")

# iteration ==============================
# by keys
>>> for i in keys(t.SOFTWARE.RegTest):
...    print repr(i)
Winreg(winreg.HKEY_CURRENT_USER, r"SOFTWARE\\RegTest\\test1")
Winreg(winreg.HKEY_CURRENT_USER, r"SOFTWARE\\RegTest\\test2")
Winreg(winreg.HKEY_CURRENT_USER, r"SOFTWARE\\RegTest\\test3")

# by values    
>>> list(values(t.SOFTWARE.RegTest.test1))
[('value1', u'val1'), ('value2', 1), ('value3', 2)]

# deletion ==============================
>>> delete(t.SOFTWARE.RegTest.test1.value3)
>>> delete(t.SOFTWARE.RegTest.test3)
>>> delete(t.SOFTWARE.RegTest.test1)
>>> delete(t.SOFTWARE.RegTest.test2)
>>> delete(t.SOFTWARE.RegTest)
>>> delete(t.SOFTWARE.RegTest2)


winreg.py:
import _winreg, os
from _winreg import HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, HKEY_CLASSES_ROOT,\
    HKEY_CURRENT_CONFIG, HKEY_DYN_DATA, HKEY_PERFORMANCE_DATA, HKEY_USERS

hk2text = {
    HKEY_LOCAL_MACHINE: 'HKEY_LOCAL_MACHINE',
    HKEY_CURRENT_USER: 'HKEY_CURRENT_USER',
    HKEY_CLASSES_ROOT: 'HKEY_CLASSES_ROOT',
    HKEY_CURRENT_CONFIG: 'HKEY_CURRENT_CONFIG',
    HKEY_DYN_DATA: 'HKEY_DYN_DATA',
    HKEY_PERFORMANCE_DATA: 'HKEY_PERFORMANCE_DATA',
    HKEY_USERS: 'HKEY_USERS',
}
   
class Winreg:
    def __init__(self, root=None, location=''):
        self.__dict__['location'] = location
        self.__dict__['root'] = root
    def __getattr__(self, location):
        return Winreg(self.__dict__['root'], os.path.join(self.__dict__['location'], location))
    def __getitem__(self, location):
        return Winreg(self.__dict__['root'], os.path.join(self.__dict__['location'], location))
    def __setattr__(self, location, value):
        self.__setValue(location, value)
        return value
    def __setitem__(self, location, val):
        self.__setValue(location, value)
        return value
    def __str__(self):
        return unicode(self.__getValue())
    def __setValue(self, location, value):
        if isinstance(value, dict):
            _winreg.CreateKey(self.__dict__['root'], os.path.join(self.__dict__['location'], location))
        elif isinstance(value, unicode):
            key = _winreg.CreateKey(self.__dict__['root'], self.__dict__['location'])
            _winreg.SetValueEx(key, location, 0, _winreg.REG_SZ, value)
        elif isinstance(value, int):
            key = _winreg.CreateKey(self.__dict__['root'], self.__dict__['location'])
            _winreg.SetValueEx(key, location, 0, _winreg.REG_DWORD, value)
        else:
            raise TypeError("valid types: dict, unicode, int")
    def __getValue(self):
        try:
            a,b = os.path.split(self.__dict__['location'])
            key = _winreg.OpenKey(self.__dict__['root'], a)
            v = _winreg.QueryValueEx(key, b)
            return v[0]
        except WindowsError, e:
            if e.winerror == 2:
                raise WindowsError(e.winerror, 'Value not found: '+self.__repr__())
            else:
                raise WindowsError(e.winerror, self.__repr__())
    def __int__(self):
        return int(self.__getValue())
    def __coerce__(self, other):
        return self.__getValue(), other
    def __repr__(self):
        return 'Winreg(winreg.%s, r"%s")'%(hk2text[self.__dict__['root']], self.__dict__['location'])

def keys(reg):
    key = _winreg.OpenKey(reg.__dict__['root'], reg.__dict__['location'])
    class RegKeysIterator:
        current = 0
        def __iter__(self):
            return self
        def next(self):
            try:
                v = reg[_winreg.EnumKey(key, self.current)]
                self.current += 1
            except WindowsError, e:
                if e.winerror == 259:
                    raise StopIteration
                else:
                    raise
            return v
    return RegKeysIterator()

def values(reg):
    key = _winreg.OpenKey(reg.__dict__['root'], reg.__dict__['location'])
    class RegValuesIterator:
        current = 0
        def __iter__(self):
            return self
        def next(self):
            try:
                v = _winreg.EnumValue(key, self.current)[:2]
                self.current += 1
                return v
            except WindowsError, e:
                if e.winerror == 259:
                    raise StopIteration
                else:
                    raise
    return RegValuesIterator()

def delete(reg):
    a,b = os.path.split(reg.__dict__['location'])
    try:
        key = _winreg.OpenKey(reg.__dict__['root'], a, 0, _winreg.KEY_WRITE)
        try:
            _winreg.DeleteValue(key, b)
        except:
            _winreg.DeleteKey(key, b)
    except WindowsError, e:
        raise WindowsError(e.winerror, 'Can not delete: ' + reg.__repr__())
python winreg windows
Re: [Python] Библиотека для работы с реестром Windows
От: Critical Error ICQ: 123736611
Дата: 06.10.09 05:05
Оценка:
Разместил проект на bitbucket: http://bitbucket.org/roman/winreg/
Re: [Python] Библиотека для работы с реестром Windows
От: Аноним  
Дата: 06.10.09 10:29
Оценка:
Здравствуйте, Critical Error, Вы писали:

CE>Думаю многие windows-программеры, работающие с реестром натыкались на жутко неудобный api. Во многих проектах имеются всяческие обертки над этими апи, чтобы хоть както упростить работу. Python не исключение, так как стандартная библиотека _winreg представляет из себя простую обертку над функциями winapi.


Не раз слышал, что windows начинает тормозить после нескольких месяцев использования от разросшегося реестра. Праздное любопытство так и подталкивает написать небольшой скрипт на питоне для эксперимента: не сдохнет ли винда от добавления 10 млн ключей, а от того количества, когда реестр перестанет целиком помещаться в памяти?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.