Welcome, guest | Sign In | My Account | Store | Cart

The _winreg module is a thin wrapper around the Windows C API to the Windows Registry. As a thin wrapper, it's not very Pythonic. This recipe defines a class using the MutableMapping ABC to create a dictionary-like interface to the Windows Registry.

Python, 120 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import collections, os.path
import _winreg

# Alternative to support unicode in Python 2
# http://pypi.python.org/pypi/winreg_unicode
#import winreg_unicode as _winreg 

for key in dir(_winreg):
    if key.startswith('HKEY_'):
        globals()[key[5:]] = getattr(_winreg, key)
del key

def interpret(value_type, value):
    if value_type == _winreg.REG_SZ:
        return value
    elif value_type == _winreg.REG_EXPAND_SZ:
        return os.path.expandvars(value)
    else:
        return None

class HiveKeyIterator(collections.KeysView):
    def __init__(self, hivekey):
        self._key = _winreg.OpenKey(hivekey._hive, hivekey._key)
        self._index = 0
        self._done = False

    def next(self):
        if self._done:
            raise StopIteration
        while True:
            for i in range(3):
                try:
                    name, data, data_type = _winreg.EnumValue(self._key,
                                                              self._index)
                    break
                except WindowsError:
                    continue
            else:
                self._done = True
                self._key.Close()
                raise StopIteration

            self._index += 1
            rv = interpret(data_type, name)
            if rv is not None:
                return rv

class HiveKey(collections.MutableMapping):
    def __init__(self, hive, key=''):
        self._hive = hive
        self._key = key

    def _getvalue(self, key, subkey):
        with _winreg.OpenKey(self._hive, key) as root_key:
            value, value_type = _winreg.QueryValueEx(root_key, subkey)
        rv = interpret(value_type, value)
        if rv is None:
            raise NotImplementedError('type: %d' % value_type)
        return rv

    def __getitem__(self, key):
        key, subkey = self._compute_subkey(key)
        try:
            return self._getvalue(key, subkey)
        except WindowsError:
            pass
        key = key + '\\' + subkey
        try:
            with _winreg.OpenKey(self._hive, key): # verify that key exists
                pass
        except WindowsError:
            raise KeyError
        return HiveKey(self._hive, key)

    def __iter__(self):
        return HiveKeyIterator(self)

    def __len__(self):
        "value is approximate since .keys() drops non-string types"
        with _winreg.OpenKey(self._hive, self._key) as k:
            num_subkeys, num_values, t = _winreg.QueryInfoKey(k)
            return num_values

    def _compute_subkey(self, k):
        key = (self._key + '\\' + k.strip('\\')).strip('\\')
        subkeys = key.split('\\')
        key = '\\'.join(subkeys[:-1])
        subkey = subkeys[-1]
        return key, subkey

    def __setitem__(self, k, v):
        if type(v) != type(u''):
            raise NotImplementedError
        key, subkey = self._compute_subkey(k)
        with _winreg.CreateKey(self._hive, key) as root_key:
            _winreg.SetValueEx(root_key, subkey, 0, _winreg.REG_SZ, v)

    def __delitem__(self, k):
        key, subkey = self._compute_subkey(k)
        with _winreg.OpenKey(self._hive, key,
                             0, _winreg.KEY_ALL_ACCESS) as root_key:
            try:
                _winreg.DeleteValue(root_key, subkey)
            except WindowsError:
                try:
                    _winreg.DeleteKey(root_key, subkey)
                except WindowsError:
                    raise KeyError

    def get_keys(self):
        values = []
        with _winreg.OpenKey(self._hive, self._key) as root_key:
            try:
                for i in range(100000):
                    key = _winreg.EnumKey(root_key, i)
                    if '\x00' in key: continue
                    values.append(key)
            except WindowsError:
                pass
        return values

Example usage:

user = HiveKey(CURRENT_USER)
software = HiveKey(LOCAL_MACHINE, 'Software')
print list(software)

software['muahhaha\\test\\foo'] = u'bat'
del software['muahhaha\\test\\foo']
del software['muahhaha\\test']
del software['muahhaha']

print user['Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager\\DllName']

1 comment

Stephen Chappell 13 years, 7 months ago  # | flag

You may be interested in reviewing the set of "Windows Registry" related recipes: http://code.activestate.com/recipes/sets/16-windows-registry/

Created by Daniel Stutzbach on Wed, 1 Sep 2010 (MIT)
Python recipes (4591)
Daniel Stutzbach's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks