Pure-Python reader for Korean HWP 5.x and HWPX documents — text and tables. Clean-room, permissively licensed.
Project description
syhwp
Pure-Python reader for Korean HWP 5.x and HWPX documents. Extracts text, tables, equations and images as plain text, GitHub-flavored Markdown, or HTML — with a single small dependency and a permissive (MIT) license.
import syhwp
text = syhwp.extract_text("report.hwp") # plain text
md = syhwp.extract_markdown("report.hwpx") # markdown (tables as pipe tables)
html = syhwp.extract_html("report.hwp") # standalone HTML
The format (HWP vs HWPX) is detected automatically, so .hwp and .hwpx are
handled the same way.
Install
pip install syhwp
The only runtime dependency is olefile
(BSD). HWPX parsing uses the standard library alone.
Command line
syhwp report.hwp # markdown (default)
syhwp report.hwp --text # plain text
syhwp report.hwpx --html # HTML
python -m syhwp report.hwp # equivalent
Library API
Convenience functions — each takes a path and returns a string:
extract_text(path)— plain textextract_markdown(path)— GFM markdown; tables become pipe tablesextract_html(path)— a standalone HTML documentdetect_format(path)—"hwp5"or"hwpx"
Structured access via open():
doc = syhwp.open("report.hwp") # -> Document
doc.version # e.g. "5.1.0.1"
doc.text, doc.markdown, doc.html # rendered forms
for table in doc.tables: # Table(n_rows, n_cols, cells)
print(table.to_markdown())
for cell in table.cells: # Cell(row, col, text, row_span, col_span)
...
for para in doc.paragraphs: # Paragraph(text)
print(para.text)
for eq in doc.equations: # Equation(script)
print(eq.script)
Blocks appear in reading order in doc.blocks as Paragraph, Table,
Equation, or Image.
Features
- HWP 5.x (legacy OLE binary) and HWPX (OWPML) in one library.
- Tables reconstructed into a grid (Markdown pipe tables / HTML
<table>). - Equations surfaced as their script; images/drawings as a
[그림]placeholder. - Robust by design: unknown records are skipped, and malformed or corrupt input
raises a typed
SyhwpErrorinstead of crashing (fuzz-tested). - Pure Python 3.9–3.13, one dependency, no external services or servers.
Limitations
- Password-protected and distribution (copy-protected) documents cannot be
read — their body is encrypted; these raise
EncryptedDocumentError. - Merged table cells are captured in the model (
row_span/col_span), but Markdown output leaves the covered cells blank (Markdown cannot merge cells). - HWP 3.x and earlier (a different, pre-5.0 format) are not supported.
Why another HWP library?
The existing Python options each have a blocker for commercial or SaaS use:
| Library | License | Note |
|---|---|---|
pyhwp |
AGPL-3.0 | Network copyleft — unsuitable for closed / SaaS use |
libhwp (hwp-rs) |
Apache-2.0 | Unmaintained; no Python 3.12+ wheels |
pyhwpx |
— | Windows-only (COM automation) |
syhwp aims to be the permissively-licensed, maintained, pure-Python option, and
adds HWPX support and Markdown / HTML output.
Provenance
syhwp is a clean-room implementation written from HANCOM's publicly
published HWP 5.0 binary format and OWPML (HWPX) specifications. It does not
derive from or incorporate the AGPL-licensed pyhwp, which is what allows the
permissive MIT license.
See DESIGN.md for architecture and file-format notes.
License
MIT © 2026 sysphere
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 Distribution
Built Distribution
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 syhwp-0.0.6.tar.gz.
File metadata
- Download URL: syhwp-0.0.6.tar.gz
- Upload date:
- Size: 32.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eebcb9cd747a8346665ebd97af5fd12318f44380606fe71501f60ce718065889
|
|
| MD5 |
325085e25e8d2d9eeb3cb252c20ab952
|
|
| BLAKE2b-256 |
8b0dc4c537c716b895b5392d2cd47901a6f251d6678564f65ada1fa7304ca699
|
Provenance
The following attestation bundles were made for syhwp-0.0.6.tar.gz:
Publisher:
publish.yml on sysphere/syhwp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
syhwp-0.0.6.tar.gz -
Subject digest:
eebcb9cd747a8346665ebd97af5fd12318f44380606fe71501f60ce718065889 - Sigstore transparency entry: 2167243031
- Sigstore integration time:
-
Permalink:
sysphere/syhwp@0fb2ca3101faf6a9b252dc8c3d59ec695f5ef661 -
Branch / Tag:
refs/tags/v0.0.6 - Owner: https://github.com/sysphere
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0fb2ca3101faf6a9b252dc8c3d59ec695f5ef661 -
Trigger Event:
push
-
Statement type:
File details
Details for the file syhwp-0.0.6-py3-none-any.whl.
File metadata
- Download URL: syhwp-0.0.6-py3-none-any.whl
- Upload date:
- Size: 15.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
305ca5c0c1dafe4bb27a7b1523195c3a08604ca8e7f71b44cb8d4c5b0eab1ffb
|
|
| MD5 |
cfb4b9f5e7d32b0b292c33f8ba339bcd
|
|
| BLAKE2b-256 |
40c4cda0d02c326afb52df7b231c23ddb20445fdec1aa3ab2b4238c5d927a98c
|
Provenance
The following attestation bundles were made for syhwp-0.0.6-py3-none-any.whl:
Publisher:
publish.yml on sysphere/syhwp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
syhwp-0.0.6-py3-none-any.whl -
Subject digest:
305ca5c0c1dafe4bb27a7b1523195c3a08604ca8e7f71b44cb8d4c5b0eab1ffb - Sigstore transparency entry: 2167243080
- Sigstore integration time:
-
Permalink:
sysphere/syhwp@0fb2ca3101faf6a9b252dc8c3d59ec695f5ef661 -
Branch / Tag:
refs/tags/v0.0.6 - Owner: https://github.com/sysphere
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0fb2ca3101faf6a9b252dc8c3d59ec695f5ef661 -
Trigger Event:
push
-
Statement type: