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.
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']
You may be interested in reviewing the set of "Windows Registry" related recipes: http://code.activestate.com/recipes/sets/16-windows-registry/