Skip to main content

a more pythonic way to access the windows registry as winreg

Project description

lib_registry

CI CodeQL License: MIT Open in Codespaces PyPI PyPI - Downloads Code Style: Ruff codecov Maintainability Known Vulnerabilities security: bandit

A more pythonic way to access the Windows registry as winreg.

Wraps Python's winreg module with a high-level Registry class providing connection caching, automatic type detection, recursive key operations, and a context manager. On non-Windows platforms, fake_winreg provides a simulated registry so tests and code run everywhere.

Features

  • Pythonic Registry class with context manager support
  • Automatic registry value type detection (str, int, bytes, list)
  • Connection and key handle caching for performance
  • Recursive key creation (parents=True) and deletion (delete_subkeys=True)
  • Remote computer registry access
  • SID enumeration and username resolution
  • Save/load registry subtrees to/from files
  • WOW64 32/64-bit registry view support
  • Registry reflection control
  • Cross-platform via fake_winreg on Linux/macOS
  • CLI entry point with rich-click styling

Install

pip install lib_registry

Or with uv (recommended):

uv pip install lib_registry

For all installation methods (pipx, uvx, poetry, etc.), see INSTALL.md.

Python 3.10+ Baseline

  • Targets Python 3.10 and newer
  • Runtime dependencies: rich-click for CLI output, rtoml for TOML parsing, fake_winreg on non-Windows platforms
  • CI covers CPython 3.10 through 3.14

Usage

As a library

import lib_registry

# Create a registry accessor
registry = lib_registry.Registry()

# Check if a key exists
registry.key_exist('HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion')

# Read a value
build = registry.get_value(
    'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion',
    'CurrentBuild',
)

# Create a key and write values
registry.create_key('HKCU\\Software\\MyApp', parents=True)
registry.set_value('HKCU\\Software\\MyApp', 'Setting', 'value')
registry.set_value('HKCU\\Software\\MyApp', 'Count', 42)

# Iterate subkeys and values
for subkey in registry.subkeys('HKEY_USERS'):
    print(subkey)

for name, data, reg_type in registry.values('HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'):
    print(f'{name} = {data}')

# Save and load registry subtrees
registry.save_key('HKCU\\Software\\MyApp', '/tmp/myapp_backup.json')
registry.load_key(lib_registry.winreg.HKEY_CURRENT_USER, 'Software\\MyAppCopy', '/tmp/myapp_backup.json')

# Clean up
registry.delete_key('HKCU\\Software\\MyApp', delete_subkeys=True)

# SID / user operations (no try/except needed — .DEFAULT handled gracefully)
for sid in registry.sids():
    print(f'{sid} -> {registry.username_from_sid(sid)}')

# Reverse lookup: find SID by username
sid = registry.sid_from_username('alice')

# Use as context manager (handles closed automatically)
with lib_registry.Registry('HKLM') as reg:
    info = reg.key_info('HKLM\\SOFTWARE')

Path separators

Both backslashes and forward slashes are accepted in registry paths:

# These are equivalent:
registry.key_exist('HKLM\\SOFTWARE\\Microsoft')
registry.key_exist('HKLM/SOFTWARE/Microsoft')

CLI Reference

All commands accept registry paths with either backslashes (\) or forward slashes (/). Hive names are case-insensitive (HKLM, hklm, HKEY_LOCAL_MACHINE all work). Run any command with -h for built-in help.

Global options

lib_registry [OPTIONS] COMMAND [ARGS]...
Option Default Description
--version Print version and exit
--traceback/--no-traceback on Show full Python traceback on errors
-q, --quiet off Suppress non-error output
--json off Emit JSON output (for scripting)
--computer HOST Connect to remote computer registry
-h, --help Show help and exit

Also available as python -m lib_registry.


info -- package metadata

lib_registry info

Print resolved package metadata (name, version, homepage, author).


get -- read a value

lib_registry get [OPTIONS] KEY VALUE_NAME
Argument/Option Required Description
KEY yes Registry key path (e.g. HKLM/SOFTWARE/...)
VALUE_NAME yes Name of the value to read (omit for default)
--type no Also display the REG_* type alongside the data
--default no Read the unnamed default value

Examples:

lib_registry get "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion" CurrentBuild
# Output: 19045

lib_registry get --type "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion" CurrentBuild
# Output: REG_SZ: 19045

set -- write a value

lib_registry set [OPTIONS] KEY VALUE_NAME DATA
Argument/Option Required Description
KEY yes Registry key path
VALUE_NAME yes Name of the value to write
DATA yes Value data as string (converted based on --type)
--type TYPE no Registry type. One of: REG_SZ, REG_DWORD, REG_QWORD, REG_BINARY, REG_MULTI_SZ, REG_EXPAND_SZ, REG_NONE, etc. Without --type, data is always stored as REG_SZ (string). Use --type REG_DWORD explicitly for integers.
--default no Write the unnamed default value (VALUE_NAME ignored)

Type conversion rules:

--type DATA is parsed as Example
(omitted) always string (REG_SZ) 42 -> REG_SZ, hello -> REG_SZ
REG_SZ string "hello world"
REG_DWORD integer (32-bit) 42
REG_QWORD integer (64-bit) 9999999999
REG_BINARY UTF-8 encoded bytes "raw data"
REG_MULTI_SZ \0-delimited string list "line1\0line2\0line3"
REG_NONE None (empty) (DATA ignored)

Examples:

lib_registry set HKCU/Software/MyApp Setting "hello world"
lib_registry set HKCU/Software/MyApp Count 42 --type REG_DWORD
lib_registry set HKCU/Software/MyApp Paths "C:\bin\0D:\tools" --type REG_MULTI_SZ

Silent on success (exit code 0).


delete-value -- remove a value

lib_registry delete-value KEY VALUE_NAME
Argument/Option Required Description
KEY yes Registry key path
VALUE_NAME yes Name of the value to delete
--force no Suppress error if value does not exist

Silent on success.


list -- list subkeys and values

lib_registry list [OPTIONS] KEY
Argument/Option Required Description
KEY yes Registry key path
--keys no Show subkeys only
--values no Show values only
--recursive, -r no Recurse into subkeys

Without flags, shows both subkeys and values. Output format:

[KEY] SubkeyName
[REG_SZ] ValueName = data
[REG_DWORD] Count = 42

Examples:

lib_registry list HKEY_USERS
lib_registry list --keys HKEY_USERS
lib_registry list --values "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion"

exists -- check key existence

lib_registry exists KEY
Argument Required Description
KEY yes Registry key path

Produces no output. Exit code 0 if the key exists, 1 if it does not. Designed for shell scripting:

if lib_registry exists HKCU/Software/MyApp; then
    echo "Key exists"
fi

create-key -- create a registry key

lib_registry create-key [OPTIONS] KEY
Argument/Option Required Description
KEY yes Registry key path to create
--parents no Create intermediate parent keys if missing

Silent on success. Without --parents, fails if the parent key does not exist.

Examples:

lib_registry create-key HKCU/Software/MyApp
lib_registry create-key HKCU/Software/MyApp/Deep/Nested/Key --parents

delete-key -- delete a registry key

lib_registry delete-key [OPTIONS] KEY
Argument/Option Required Description
KEY yes Registry key path to delete
--recursive no Also delete all subkeys and their values recursively
--force no Suppress error if key does not exist

Silent on success. Without --recursive, fails if the key has subkeys.

Examples:

lib_registry delete-key HKCU/Software/MyApp
lib_registry delete-key HKCU/Software/MyApp --recursive

export -- save a key subtree to file

lib_registry export KEY FILE
Argument Required Description
KEY yes Registry key path to export
FILE yes Output file path (JSON format)

Saves the key and all its subkeys/values to a JSON file. Use import to restore.

lib_registry export HKCU/Software/MyApp backup.json

import -- load a key subtree from file

lib_registry import KEY SUB_KEY FILE
Argument Required Description
KEY yes Hive or parent key (e.g. HKCU)
SUB_KEY yes Subkey path under KEY where data will be loaded
FILE yes Input file path (JSON, as produced by export)
lib_registry import HKCU Software/MyAppCopy backup.json

search -- find values by pattern

lib_registry search [OPTIONS] KEY
Argument/Option Required Description
KEY yes Registry key path to search under (recursive)
--name PATTERN no Glob pattern to match value names (e.g. "Install*")
--data PATTERN no Glob pattern to match value data (e.g. "*Microsoft*")

Recursively walks all subkeys under KEY and prints matching values. At least one of --name or --data should be specified.

Output format:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion  [REG_SZ] CurrentBuild = 19045

Examples:

lib_registry search "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion" --name "Current*"
lib_registry search HKLM/SOFTWARE --data "*Python*"

users -- list Windows users from registry

lib_registry users

No arguments. Enumerates SIDs from the ProfileList and resolves usernames. Output is a formatted table:

      Registry Users
+-----------------------+----------+
| SID                   | Username |
+-----------------------+----------+
| S-1-5-21-...-1000     | alice    |
| S-1-5-18              | SYSTEM   |
+-----------------------+----------+

sid -- resolve a SID to a username

lib_registry sid SID
Argument Required Description
SID yes Security Identifier to resolve

Prints the username for the given SID. Handles .DEFAULT gracefully.

lib_registry sid S-1-5-21-1234567890-1234567890-1234567890-1001
# Output: alice

lib_registry sid .DEFAULT
# Output: Default

lib_registry --json sid .DEFAULT
# Output: {"sid": ".DEFAULT", "username": "Default"}

whoami -- resolve a username to its SID

lib_registry whoami USERNAME
Argument Required Description
USERNAME yes Windows username to look up

Reverse lookup: finds the SID for the given username (case-insensitive).

lib_registry whoami alice
# Output: S-1-5-21-1234567890-1234567890-1234567890-1001

lib_registry --json whoami alice
# Output: {"username": "alice", "sid": "S-1-5-21-..."}

tree -- visual key hierarchy

lib_registry tree [OPTIONS] KEY
Argument/Option Required Description
KEY yes Registry key path
--depth N no Maximum depth to display (default: 3)

Displays a Rich tree view of the key hierarchy. With --json, outputs a nested dict.

lib_registry tree HKEY_USERS --depth 2
lib_registry --json tree HKLM/SOFTWARE --depth 1

copy -- copy a key

lib_registry copy [OPTIONS] SRC_KEY DST_KEY
Argument/Option Required Description
SRC_KEY yes Source key path
DST_KEY yes Destination key path (created if needed)
--recursive no Also copy all subkeys recursively

Copies all values from SRC_KEY to DST_KEY. With --recursive, copies the entire subtree.

lib_registry copy HKCU/Software/MyApp HKCU/Software/MyAppBackup --recursive

rename -- rename a value

lib_registry rename KEY OLD_NAME NEW_NAME
Argument Required Description
KEY yes Registry key path
OLD_NAME yes Current value name
NEW_NAME yes New value name

Renames a registry value by copying its data and type to the new name, then deleting the old name. Atomic within a single key.

lib_registry rename HKCU/Software/MyApp OldSetting NewSetting

diff -- compare two keys

lib_registry diff KEY_A KEY_B
Argument Required Description
KEY_A yes First key path to compare
KEY_B yes Second key path to compare

Recursively compares values and subkeys between two registry key subtrees. Shows values only in A, only in B, and values that differ.

lib_registry diff HKCU/Software/MyApp HKCU/Software/MyAppBackup
lib_registry --json diff HKCU/Software/V1 HKCU/Software/V2

Output format:

  - HKCU\Software\MyApp  (only in KEY_A)
  + HKCU\Software\MyAppBackup  (only in KEY_B)
  ~ HKCU\Software\MyApp / Setting
    A: old_value
    B: new_value

Access constants

All winreg KEY_* access constants are re-exported for convenience:

from lib_registry import KEY_READ, KEY_WRITE, KEY_ALL_ACCESS, KEY_WOW64_64KEY

API Reference

Constructor

Registry(key=None, computer_name=None)

Create a registry accessor. Optionally connect to a hive immediately. Supports context manager (with Registry('HKLM') as reg:).

# Local registry
reg = Registry()

# Connect to hive at creation
reg = Registry('HKLM')

# Remote computer
reg = Registry('HKLM', computer_name='server01')

# Context manager — handles closed automatically
with Registry('HKCU') as reg:
    build = reg.get_value('HKCU\\Software\\Microsoft', 'Version')

Key Operations

create_key(key, sub_key='', exist_ok=True, parents=False) -> HKEYType

Create a registry key and return a handle.

reg.create_key('HKCU/Software/MyApp')                    # existing key OK
reg.create_key('HKCU/Software/MyApp', exist_ok=False)     # raises if exists
reg.create_key('HKCU/Software/A/B/C', parents=True)       # create intermediates

create_key_ex(key, sub_key='', access=KEY_WRITE) -> HKEYType

Create with explicit access mask (for WOW64 scenarios).

from lib_registry import KEY_WOW64_64KEY
reg.create_key_ex('HKCU/Software/MyApp', access=KEY_WOW64_64KEY)

delete_key(key, sub_key='', missing_ok=False, delete_subkeys=False)

Delete a key. Fails if key has children unless delete_subkeys=True.

reg.delete_key('HKCU/Software/MyApp')                         # leaf key only
reg.delete_key('HKCU/Software/MyApp', delete_subkeys=True)    # recursive
reg.delete_key('HKCU/Software/Missing', missing_ok=True)      # no error if absent

delete_key_ex(key, sub_key='', access=KEY_WOW64_64KEY)

Delete with WOW64 view control.

key_exist(key, sub_key='') -> bool

if reg.key_exist('HKLM/SOFTWARE/Python'):
    print("Python is installed")

key_info(key, sub_key='') -> tuple[int, int, int]

Returns (number_of_subkeys, number_of_values, last_modified_win_timestamp).

subkeys, values, ts = reg.key_info('HKLM/SOFTWARE')

number_of_subkeys(key, sub_key='') -> int

number_of_values(key, sub_key='') -> int

has_subkeys(key, sub_key='') -> bool

last_access_timestamp(key, sub_key='') -> float

Unix epoch timestamp (seconds since 1970-01-01).

last_access_timestamp_windows(key, sub_key='') -> int

Windows timestamp (100ns intervals since 1601-01-01).


Subkey & Value Iteration

subkeys(key, sub_key='') -> Iterator[str]

for name in reg.subkeys('HKEY_USERS'):
    print(name)

values(key, sub_key='') -> Iterator[tuple[str, RegData, int]]

Yields (value_name, value_data, value_type_int) tuples.

for name, data, reg_type in reg.values('HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion'):
    print(f'{name} ({reg_type}) = {data}')

Value Operations

get_value(key, value_name) -> RegData

Read a value's data. Pass None or '' as value_name for the unnamed default value.

build = reg.get_value('HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion', 'CurrentBuild')

get_value_ex(key, value_name) -> tuple[RegData, int]

Read data and registry type.

data, reg_type = reg.get_value_ex('HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion', 'CurrentBuild')
# reg_type is e.g. winreg.REG_SZ (1)

set_value(key, value_name, value, value_type=None)

Write a value. Type is auto-detected from the Python type if value_type is None.

Python type Auto-detected REG_TYPE
str REG_SZ
int REG_DWORD
bytes REG_BINARY
list[str] REG_MULTI_SZ
None REG_NONE
reg.set_value('HKCU/Software/MyApp', 'Name', 'Alice')              # REG_SZ
reg.set_value('HKCU/Software/MyApp', 'Count', 42)                  # REG_DWORD
reg.set_value('HKCU/Software/MyApp', 'Data', b'\x00\x01')          # REG_BINARY
reg.set_value('HKCU/Software/MyApp', 'Paths', ['C:\\', 'D:\\'])     # REG_MULTI_SZ
reg.set_value('HKCU/Software/MyApp', 'Env', '%PATH%', winreg.REG_EXPAND_SZ)  # explicit type

delete_value(key, value_name)

reg.delete_value('HKCU/Software/MyApp', 'Name')

File Operations

save_key(key, file_name, sub_key='')

Save a key subtree to a file (JSON with fake_winreg, binary hive on Windows).

reg.save_key('HKCU/Software/MyApp', '/tmp/backup.json')

load_key(key, sub_key, file_name)

Load a subtree from file into a registry location.

reg.load_key(winreg.HKEY_CURRENT_USER, 'Software/MyAppCopy', '/tmp/backup.json')

flush_key(key, sub_key='')

Force pending writes to disk (rarely needed).


Handle Management

close_key(key, sub_key='')

Explicitly close a cached key handle.

close_all()

Close all cached key handles and hive connections. Called automatically by __exit__.


SID / User Operations

sids() -> Iterator[str]

Iterate SIDs from the ProfileList.

for sid in reg.sids():
    print(sid)   # e.g. 'S-1-5-21-...-1001'

username_from_sid(sid) -> str

Resolve a SID to a username. Returns "Default" for .DEFAULT.

reg.username_from_sid('S-1-5-21-...-1001')   # 'alice'
reg.username_from_sid('.DEFAULT')              # 'Default'

sid_from_username(username) -> str

Reverse lookup (case-insensitive).

reg.sid_from_username('alice')    # 'S-1-5-21-...-1001'
reg.sid_from_username('Default')  # '.DEFAULT'

Reflection Control (64-bit Windows)

disable_reflection_key(key, sub_key='')

enable_reflection_key(key, sub_key='')

query_reflection_key(key, sub_key='') -> bool

Returns True if reflection is disabled.


Utility

expand_environment_strings(string) -> str (static method)

Expand %VAR% references.

Registry.expand_environment_strings('%USERPROFILE%\\Documents')
# '/home/alice/Documents' (or 'C:\Users\alice\Documents' on Windows)

Helper Functions (module-level)

from lib_registry import resolve_key, get_key_as_string, normalize_separators

resolve_key('HKLM/SOFTWARE/Microsoft')           # (HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft')
get_key_as_string(winreg.HKEY_LOCAL_MACHINE)      # 'HKEY_LOCAL_MACHINE'
normalize_separators('HKLM/SOFTWARE/test')        # 'HKLM\\SOFTWARE\\test'

Type Alias

RegData = None | bytes | int | str | list[str]

All registry values are one of these types.


Exception Hierarchy

RegistryError
  RegistryConnectionError
  RegistryKeyError
    RegistryKeyNotFoundError
    RegistryKeyExistsError
    RegistryKeyCreateError
    RegistryKeyDeleteError
  RegistryValueError
    RegistryValueNotFoundError
    RegistryValueDeleteError
    RegistryValueWriteError
  RegistryHKeyError
  RegistryNetworkConnectionError
  RegistryHandleInvalidError
from lib_registry import Registry, RegistryKeyNotFoundError

reg = Registry()
try:
    reg.get_value('HKCU/Software/NoSuchApp', 'key')
except RegistryKeyNotFoundError:
    print("Key not found")

Access Constants

Re-exported from winreg for convenience:

from lib_registry import (
    KEY_READ, KEY_WRITE, KEY_ALL_ACCESS,
    KEY_WOW64_32KEY, KEY_WOW64_64KEY,
    KEY_QUERY_VALUE, KEY_SET_VALUE,
    KEY_CREATE_SUB_KEY, KEY_ENUMERATE_SUB_KEYS,
    KEY_NOTIFY, KEY_CREATE_LINK, KEY_EXECUTE,
)

Further Documentation

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lib_registry-3.1.2.tar.gz (63.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lib_registry-3.1.2-py3-none-any.whl (31.8 kB view details)

Uploaded Python 3

File details

Details for the file lib_registry-3.1.2.tar.gz.

File metadata

  • Download URL: lib_registry-3.1.2.tar.gz
  • Upload date:
  • Size: 63.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for lib_registry-3.1.2.tar.gz
Algorithm Hash digest
SHA256 2afdb82a158cfbf2a85a6ed1f0716b627f0bd3dcc2f8ea90e79ca328058df72e
MD5 08b317a236477b5bd82b00ccb9dcaebe
BLAKE2b-256 1ae64821d0ece476ec95dad3fc32570de783aaf8c865c68078c7c22df4ce9c5f

See more details on using hashes here.

File details

Details for the file lib_registry-3.1.2-py3-none-any.whl.

File metadata

  • Download URL: lib_registry-3.1.2-py3-none-any.whl
  • Upload date:
  • Size: 31.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for lib_registry-3.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ef03cb309bd70e36673a1087f4fbb836e4b81871c9a9adba1a42f4d35b4c05e3
MD5 49a1cacabadb5ba0774dcf130acfbb9a
BLAKE2b-256 e10780045473cd1abe956903f01dd260463d7108257ffb207048dbaf443ca3f1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page