unhwp
High-performance Python library for extracting HWP/HWPX Korean word processor documents to Markdown.
Installation
pip install unhwp
Quick Start
import unhwp
# Simple conversion
markdown = unhwp.to_markdown("document.hwp")
print(markdown)
# Extract plain text
text = unhwp.extract_text("document.hwp")
# Full parsing with images
with unhwp.parse("document.hwp") as result:
print(result.markdown)
print(f"Sections: {result.section_count}")
print(f"Paragraphs: {result.paragraph_count}")
# Save images
for img in result.images:
img.save(f"output/{img.name}")
Handling Failures
UnhwpError.kind says why a call failed, so you can react to the reason instead of
matching on message text:
from unhwp import ErrorKind, ParseError
try:
with unhwp.parse(path) as result:
print(result.markdown)
except ParseError as err:
if err.kind in (ErrorKind.OLE_CONTAINER, ErrorKind.ZIP_ARCHIVE):
print("The file is damaged.")
elif err.kind in (ErrorKind.UNKNOWN_FORMAT, ErrorKind.UNSUPPORTED_FORMAT):
print("Not a supported HWP/HWPX document.")
elif err.kind in (ErrorKind.ENCRYPTED, ErrorKind.DISTRIBUTION_RESTRICTED):
print("The document cannot be opened without authorization.")
else:
# Also the right branch for a reason this build has no name for.
print(f"Extraction failed ({err.kind}): {err}")
The numbers behind ErrorKind are a stable ABI contract: a new reason takes the next free
number and existing ones are never renumbered. Always keep a final else — an
unrecognised value arrives as a plain int rather than an ErrorKind, so that a newer
native library stays usable. kind is ErrorKind.OTHER for failures raised by the wrapper
itself, and never ErrorKind.NONE (which means success).
Features
- Fast: Native Rust library with zero-copy parsing
- Complete: Extracts text, tables, images, and document structure
- Clean Output: Optional cleanup pipeline for polished Markdown
- Format Support: HWP 5.0, HWPX, and HWP 3.x (legacy)
API Reference
Functions
to_markdown(path) -> str
Convert an HWP/HWPX document to Markdown.
markdown = unhwp.to_markdown("document.hwp")
to_markdown_with_cleanup(path, cleanup_options=None) -> str
Convert with optional cleanup.
markdown = unhwp.to_markdown_with_cleanup(
"document.hwp",
cleanup_options=unhwp.CleanupOptions.aggressive()
)
extract_text(path) -> str
Extract plain text content.
text = unhwp.extract_text("document.hwp")
parse(path, render_options=None) -> ParseResult
Parse a document with full access to content and images.
with unhwp.parse("document.hwp") as result:
print(result.markdown)
print(result.text)
for img in result.images:
print(img.name, len(img.data))
detect_format(path) -> int
Detect the document format.
fmt = unhwp.detect_format("document.hwp")
if fmt == unhwp.FORMAT_HWP5:
print("HWP 5.0 format")
elif fmt == unhwp.FORMAT_HWPX:
print("HWPX format")
Classes
RenderOptions
Options for Markdown rendering.
opts = unhwp.RenderOptions(
include_frontmatter=True,
image_path_prefix="images/",
preserve_line_breaks=False,
)
CleanupOptions
Options for output cleanup.
# Presets
opts = unhwp.CleanupOptions.minimal()
opts = unhwp.CleanupOptions.default()
opts = unhwp.CleanupOptions.aggressive()
opts = unhwp.CleanupOptions.disabled()
# Custom
opts = unhwp.CleanupOptions(
enabled=True,
preset=1,
detect_mojibake=True,
)
Constants
FORMAT_UNKNOWN- Unknown formatFORMAT_HWP5- HWP 5.0 binary formatFORMAT_HWPX- HWPX XML formatFORMAT_HWP3- HWP 3.x legacy format
Platform Support
- Windows (x64)
- Linux (x64)
- macOS (x64, ARM64)
License
MIT License - see LICENSE for details.
Links
Metadata
Release files for unhwp 0.9.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| unhwp-0.9.1.tar.gz | 8.1 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unhwp-0.9.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.1 MB
Release files / unhwp-0.9.1.tar.gz
| Download URL | unhwp-0.9.1.tar.gz |
|---|---|
| Size | 8.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e233ad0282a77517cb622aebfd56ae0a4f2beee00d8f7585e4761c70a08ef48d
|
|
BLAKE2b-256 checksum How to use checksums |
61eeb8fbe3fe02092c59f6bd959071c57349b1ec3efbf5461779076a9daebb7c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / unhwp-0.9.1-py3-none-any.whl
| Download URL | unhwp-0.9.1-py3-none-any.whl |
|---|---|
| Size | 8.1 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
33683c31bcb12116d433f011c2a840f320231ef9af6ff0bf8b4b00fae9a85cba
|
|
BLAKE2b-256 checksum How to use checksums |
4ff766ff06dab225713e198ac52bc615b02b46832e06474a60f7a15778abba35
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|