Python bindings for bethkit — a Bethesda plugin and archive toolkit
Project description
bethkit.py
Python bindings for bethkit - a fast Rust library for reading and writing Bethesda game plugin and archive files. bethkit.py wraps the bethkit_ffi C ABI via ctypes; no compiler or build tools required.
Features
- Plugin reading - open
.esp/.esm/.eslfiles by path or from in-memory bytes; iterate groups and records; look up records by FormID or EditorID; inspect sub-records - Plugin writing - build new plugins from scratch with
PluginWriter,WritableGroup, andWritableRecord - BSA / BA2 archives - open and extract entries from BSA (TES4/SSE) and BA2 (GNRL/DX10) archives; write new archives with
BsaWriter,Ba2GnrlWriter, andBa2Dx10Writer - String tables - read, edit, and write
.STRINGS/.DLSTRINGS/.ILSTRINGSlocalisation files; apply translation sets withLocalizationSet - Schema - decode sub-records into typed
FieldValuevariants (integers, floats, FormIDs, enums with resolved names, flags, structs, arrays) viaRecordViewandSchemaRegistry - Load-order utilities -
LoadOrder,GlobalFormId, andPluginCachefor winning-override lookups and EditorID search across multiple plugins
Requirements
| Requirement | Version |
|---|---|
| Python | ≥ 3.10 |
| pydantic | ≥ 2.0 |
The native bethkit_ffi library is bundled in the wheel — no separate installation required.
Installation
uv add bethkit
or
pip install bethkit
Quick Start
Reading a plugin
from pathlib import Path
from bethkit import Plugin, Game
with Plugin.open(Path("Ordinator - Perks of Skyrim.esp"), Game.SKYRIM_SE) as plugin:
print("Masters:", plugin.masters)
print("Kind:", plugin.kind)
for group in plugin:
for child in group:
if hasattr(child, "form_id"):
print(f" 0x{child.form_id:08X} {child.editor_id}")
Building a plugin from scratch
from pathlib import Path
from bethkit import Game, PluginWriter, WritableGroup, WritableRecord
with PluginWriter(Game.SKYRIM_SE) as writer:
with WritableGroup.new(b"NPC_") as group:
rec = WritableRecord.new(b"NPC_", form_id=0x000D62)
rec.add_subrecord(b"EDID", b"MyNPC\x00")
group.add_record(rec)
writer.add_group(group)
writer.write_to_file(Path("MyMod.esp"))
Extracting from an archive
from pathlib import Path
from bethkit import Archive
with Archive.open(Path("Skyrim - Meshes.bsa")) as arc:
data = arc.extract("meshes/actors/character/character assets/skeleton.nif")
if data:
Path("skeleton.nif").write_bytes(data)
Load-order and FormID resolution
from pathlib import Path
from bethkit import Game, Plugin, PluginCache, PluginKind, LoadOrder
lo = LoadOrder()
lo.push("Skyrim.esm", PluginKind.FULL)
lo.push("MyMod.esp", PluginKind.FULL)
cache = PluginCache()
cache.add("Skyrim.esm", Plugin.open(Path("Skyrim.esm"), Game.SKYRIM_SE))
hit = cache.find_by_editor_id("ArmorIronCuirass")
if hit:
print(hit.global_form_id) # Skyrim.esm:0x012E49
print(hit.record.editor_id)
Development
git clone https://github.com/Modding-Forge/bethkit.py
cd bethkit.py
uv sync --extra dev
uv run pytest
Linting and type-checking:
uv tool run ruff check src/ tests/
uv tool run pyright src/ tests/
Related projects
- bethkit - the underlying Rust library;
bethkit.pywraps its C ABI - SSE-Auto-Translator - uses
bethkit.pyto patch localised strings
License
Apache-2.0 - see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bethkit-1.0.1-py3-none-win_amd64.whl.
File metadata
- Download URL: bethkit-1.0.1-py3-none-win_amd64.whl
- Upload date:
- Size: 38.7 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6d3dbabc871cb926ac820ad3c052dce7b51691b246d6c325ce891101553a84b
|
|
| MD5 |
d650b06463fa3b97f2d5e7abfcac66b3
|
|
| BLAKE2b-256 |
ea546cd1f2985caa8ca89d326f6bee67ae6dda3c6e82be613c47efb6d6dbc3dc
|
File details
Details for the file bethkit-1.0.1-py3-none-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: bethkit-1.0.1-py3-none-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 38.4 kB
- Tags: Python 3, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e75a8f13613e038f4605576f2192e17a1881f6ec1a815b2ae9ddd12631a3740
|
|
| MD5 |
0c5b1e555a3d45ebe747a224d117a7db
|
|
| BLAKE2b-256 |
ac2bf1b70f4127c7ea620562d6c3f8f1da1eb9ebbf36366f95297df03c5d005c
|