This recipe provides "Registry", a Windows registry wrapper class that makes it easy to work with the Windows registry. The class works with an inner class named "RegistryKey", which wraps up a Windows registry key and provides methods to access and manipulate the key information. The class provides easy to remember substitutes for long method names of _winreg.
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 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | import _winreg as wreg
class RegistryError(Exception):
""" An exception class for Registry """
def __init__(self, value):
self.value = value
def __str__(self):
return str(self.value)
class Registry(object):
""" A class which abstracts away operations on Windows
registry. This class provides a way to work with Windows
registry without using _winreg directly.
A Windows registry key is represented by the internal
class named RegistryKey. A number of operations of this
class returns and works with instances of RegistryKey.
"""
def __init__(self):
pass
def map_key(self, key):
""" Map key names to Windows registry key constants """
if type(key) is not str:
raise RegistryError,"key must be a string object"
else:
try:
return eval('wreg.' + key)
except AttributeError:
return None
class RegistryKey(object):
""" An internal class of Registry which abstracts a Windows
registry key """
def __init__(self):
# The actual PyHKEY object returned by _winreg
self._hkey = None
# The name of the key
self._keyname = ''
def open(self, key, subkey):
""" Opens a Windows registry key. The first param is one of the
Windows HKEY names or an already open key. The second param
is the actual key to open. """
if type(key) is str:
hkey = Registry.map_key(key)
else:
hkey = key
if not hkey: raise RegistryError,"could not find registry key for %s" % key
try:
self._hkey = wreg.OpenKey(hkey, subkey)
self._keyname = subkey
except EnvironmentError, e:
raise RegistryError, e
def create(self, key, subkey):
""" Creates or opens a Windows registry key. The first param
is one of the Windows HKEY names or an already open key. The
second param is the actual key to create/open. """
if type(key) is str:
hkey = Registry.map_key(key)
else:
hkey = key
if not hkey: raise RegistryError,"could not find registry key for %s" % key
try:
self._hkey = wreg.CreateKey(hkey, subkey)
self._keyname = subkey
except EnvironmentError, e:
raise RegistryError, e
def openkey(self, index):
""" Open the sub-key at the given index and return
the created RegistryKey object """
# NOTE: The index is starting from 1,not zero!
subkey = self.enumkey(index-1)
if subkey:
r = Registry.RegistryKey()
r.setkey(wreg.OpenKey(self._hkey, subkey))
r.setkeyname(subkey)
return r
else:
raise RegistryError,'No sub-key found at index %d!' % index
def enumkey(self, index):
""" Enumerate the subkeys of the currently open key """
if not self._hkey: raise RegistryError,"Error: null key"
try:
return wreg.EnumKey(self._hkey, index)
except EnvironmentError, e:
raise RegistryError, e
def enumvalue(self, index):
""" Enumerate the values of the currently open key """
if not self._hkey: raise RegistryError,"Error: null key"
try:
return wreg.EnumValue(self._hkey, index)
except EnvironmentError, e:
raise RegistryError, e
def keys(self):
""" Return the subkeys of the current key as a list """
# This method works just like the 'keys' method
# of a dictionary object.
keylist, idx = [], 0
while True:
try:
subkey=self.enumkey(idx)
keylist.append(subkey)
idx += 1
except RegistryError:
break
return keylist
def values(self):
""" Return the subvalues of the current key as a list """
# This method works just like the 'values' method
# of a dictionary object.
valuelist, idx = [], 0
while True:
try:
value=self.enumvalue(idx)
valuelist.append(value)
idx += 1
except RegistryError:
break
return valuelist
def items(self):
""" Return a list of (key,value) pairs for each subkey in the
current key """
# This method works just like the 'items' method
# of a dictionary object.
items, idx = [], 0
while True:
try:
key, value = self.enumkey(idx), self.enumvalue(idx)
items.append((key, value))
idx += 1
except RegistryError:
break
return items
def iterkeys(self):
""" Return an iterator over the list of subkeys of the current key """
# Note: this is a generator
# This method works just like the 'iterkeys' method
# of a dictionary object.
idx = 0
while True:
try:
yield self.enumkey(idx)
idx += 1
except RegistryError:
break
def itervalues(self):
""" Return an iterator over the list of subvalues of the current key """
# Note: this is a generator
# This method works just like the 'itervalues' method
# of a dictionary object.
idx = 0
while True:
try:
yield self.enumvalue(idx)
idx += 1
except RegistryError:
break
def iteritems(self):
""" Return an iterator over the (subkey,subvalue) pairs of the current key"""
# Note: this is a generator
# This method works just like the 'iteritems' method
# of a dictionary object.
idx = 0
while True:
try:
yield (self.enumkey(idx), self.enumvalue(idx))
idx += 1
except RegistryError:
break
def getvalue(self, name=''):
""" Return the value of an item inside the current key,
given its name """
try:
if name:
return wreg.QueryValueEx(self._hkey, name)
else:
return wreg.QueryValue(self._hkey, '')
except (WindowsError, EnvironmentError), e:
raise RegistryError, e
def hasvalue(self, name=''):
""" Return True if the current key has a value named
'name', False otherwise """
try:
if name:
wreg.QueryValueEx(self._hkey, name)
else:
wreg.QueryValue(self._hkey, '')
return True
except (WindowsError, EnvironmentError), e:
return False
def getkey(self):
""" Return the embedded PyHKEY object of this key """
return self._hkey
def getkeyname(self):
""" Return the name of this key """
return self._keyname
def setkey(self, hkey):
""" Set the PyHKEY object of this key """
self._hkey = hkey
def setkeyname(self, keyname):
""" Set the keyname for this key """
self._keyname = keyname
def close(self):
""" Close this key """
if self._hkey:
wreg.CloseKey(self._hkey)
def open(self, key, subkey):
""" Open a windows registry key. Same
as OpenKey of _winreg """
regkey = Registry.RegistryKey()
regkey.open(key, subkey)
return regkey
def create(self, key, subkey):
""" Create a windows registry key. Same
as CreateKey of _winreg """
regkey = Registry.RegistryKey()
regkey.create(key, subkey)
return regkey
def delete(self, key, subkey):
""" Deletes a windows registry key. Same
as DeleteKey of _winreg """
if type(key) is str:
hkey = self.map_key(key)
else:
hkey = key
if not hkey: raise RegistryError,"could not find registry key for %s" % key
try:
wreg.DeleteKey(hkey, subkey)
except EnvironmentError, e:
raise RegistryError, e
def rdelete(self, key, subkey):
""" Recursively delete a Windows registry key.
This function will remove a key, even if it
has child keys. There is no equivalent in
_winreg. """
if type(key) is str:
hkey = Registry.map_key(key)
elif type(key) is Registry.RegistryKey:
hkey = key.getkey()
else:
hkey = key
if type(subkey) is str:
subkey = self.open(hkey, subkey)
# test2
childkeys = subkey.keys()
for keyname in childkeys:
# print 'Child=>',keyname
childkey = self.open(subkey.getkey(), keyname)
self.rdelete(subkey, childkey)
# print subkey.getkeyname()
wreg.DeleteKey(hkey, subkey.getkeyname())
open = classmethod(open)
create = classmethod(create)
delete = classmethod(delete)
map_key = classmethod(map_key)
rdelete = classmethod(rdelete)
if __name__=="__main__":
key = Registry.open('HKEY_LOCAL_MACHINE', "SOFTWARE\\Python")
# Prints the RegistryKey instance
print key
# Prints the key name and the wrapped up PyHKEY instance
print key.getkeyname(), key.getkey()
corekey = key.openkey(1)
idx = 0
# Print the install path for Python 2.4 if installed.
while True:
try:
keyname = corekey.enumkey(idx)
idx += 1
if keyname == '2.4':
keyVersion = corekey.openkey(idx)
print keyVersion, keyVersion.getkeyname()
keyPath = keyVersion.openkey(2)
print keyPath, keyPath.getkeyname()
print 'Install path is %s' % keyPath.getvalue()
keyPath.close()
keyVersion.close()
break
except RegistryError:
break
corekey.close()
key.close()
|
There have been a number of recipes which try to make it easy for the programmer to work with the Windows registry. This recipe takes a different approach from them in that it is a simpler attempt at wrapping up the registry operations using an outer class with class-level methods which wraps up the operations of _winreg and an inner class which abstracts a registry key, without providing too many data structures or access points.
The design is intuitive for someone who wants to work with the Windows registry and would like to treat the keys and operations as class/object abstractions in Python rather than procedural operations using _winreg. It also has the advantage that it does not require any win32 extensions.