Skip to main content

PyO3 Python bindings for rhwp — parser and renderer for HWP/HWPX documents (Korean word processor format)

Project description

rhwp-python

한국어 | English

PyPI Python CI License: MIT

⚠️ 비공식 커뮤니티 패키지입니다. 본 프로젝트는 edwardkim/rhwp공식 배포가 아니며, rhwp 메인테이너가 직접 PyPI 에 올릴 경우를 대비해 이름을 rhwp-python 으로 양보해 둔 상태입니다. rhwp 코어 버그는 업스트림 에 보고해 주세요.

rhwp — Rust 기반 HWP/HWPX(한컴오피스 문서) 파서·렌더러 — 의 PyO3 Python 바인딩.

  • PyPI 패키지명: rhwp-python
  • Python import: import rhwp
  • Rust 코어: external/rhwp 에 git submodule 로 고정

왜 rhwp-python 인가

  • HWP + HWPX 동시 지원 — 대표 대안인 pyhwp 는 HWP5 만 지원하고 2016년 이후 유지보수 중단 상태. rhwp 는 두 포맷을 같은 API 로 처리.
  • 텍스트 추출 62배 빠름 — HWP5 기준 pyhwp 대비 96 ms vs 5,980 ms (sandbox 벤치).
  • LangChain 즉시 연동rhwp.integrations.langchain.HwpLoader 를 extras 로 제공, RAG 파이프라인에 바로 플러그인 가능.
  • 타입 완비py.typed + .pyi 스텁, pyright clean.

요구 사항

  • Python 3.10+ (abi3-py310 wheel 하나로 3.10 ~ 3.13+ 커버)
  • 코어 API 는 런타임 Python 의존성 없음
  • rhwp-python[langchain] extras 는 langchain-core>=0.2 하나만 추가 설치

설치

pip install rhwp-python
# 또는
uv add rhwp-python

사용법

import rhwp

# HWP / HWPX 파싱 — 파일 I/O + 파싱 단계에서 GIL 해제
doc = rhwp.parse("report.hwp")
print(doc.section_count, doc.paragraph_count, doc.page_count)

# 텍스트
full_text: str = doc.extract_text()          # 빈 문단 제외, "\n" 으로 join
paragraphs: list[str] = doc.paragraphs()      # 빈 문단 포함 원본 리스트

# SVG 렌더링 — 단일 페이지 또는 전체
svg_page0: str = doc.render_svg(page=0)
all_svgs: list[str] = doc.render_all_svg()
written: list[str] = doc.export_svg("output/", prefix="page")
# → page_001.svg, page_002.svg, ... (단일 페이지면 page.svg)

# PDF 렌더링 — list[int] 가 아니라 Python `bytes` 반환
pdf: bytes = doc.render_pdf()
byte_size: int = doc.export_pdf("output.pdf")

rhwp.Document(path)rhwp.parse(path) 와 동일하게 동작.

LangChain 통합

pip install "rhwp-python[langchain]"
from rhwp.integrations.langchain import HwpLoader

# 문서 전체를 단일 Document 로 (기본 — single 모드)
docs = HwpLoader("report.hwp").load()

# 빈 문단 제외, 문단 1개당 Document 1개 (RAG 청킹용 — paragraph 모드)
docs = HwpLoader("report.hwp", mode="paragraph").load()

# lazy_load: Document 를 on-the-fly 로 yield (paragraph 모드에서 O(1) peak memory)
for d in HwpLoader("report.hwp", mode="paragraph").lazy_load():
    index_into_vector_store(d)   # 사용자 파이프라인

# 표준 LangChain 텍스트 스플리터에 바로 연결
from langchain_text_splitters import RecursiveCharacterTextSplitter
chunks = RecursiveCharacterTextSplitter(chunk_size=500).split_documents(docs)

모든 Document 메타데이터: source, section_count, paragraph_count, page_count, rhwp_version. paragraph 모드에서는 paragraph_index 추가.

Document IR (v0.2.0+)

RAG / LLM 파이프라인이 직접 소비하는 구조화 문서 모델. Pydantic V2 모델 + JSON Schema (Draft 2020-12) — HWP 의 구역 / 단락 / 표 / 서식 런을 손실 없이 노출한다.

from rhwp.ir.nodes import ParagraphBlock, TableBlock

doc = rhwp.parse("report.hwp")
ir = doc.to_ir()                       # -> rhwp.ir.nodes.HwpDocument (Pydantic, frozen)
json_str = doc.to_ir_json(indent=2)    # JSON 직렬화

# 본문 블록을 순서대로 스트리밍 (표/문단 혼합, TableCell.blocks 까지 재귀)
for block in ir.iter_blocks(scope="body"):
    if isinstance(block, ParagraphBlock):
        print("P", block.prov.section_idx, block.prov.para_idx, block.text)
    elif isinstance(block, TableBlock):
        print("T", block.rows, "x", block.cols, "cells=", len(block.cells))

표 3중 표현cells (구조화 SQL/순회용) + html (HtmlRAG 호환 LLM 프롬프트) + text (평문 검색 폴백) 가 병기된다. 중첩 표는 TableCell.blocks 재귀로 자연 지원.

LangChain 통합 — 기존 loader 에 mode="ir-blocks" 추가:

from rhwp.integrations.langchain import HwpLoader

docs = HwpLoader("report.hwp", mode="ir-blocks").load()
# ^ 단락은 page_content=text, 표는 page_content=HTML. 메타에 kind / section_idx /
#   para_idx / (표의 경우) rows / cols / text / caption 포함

JSON Schemarhwp.ir.schema.export_schema() 로 Draft 2020-12 스키마 생성, load_schema() 로 in-package 동봉 JSON 로드 (네트워크 불필요). $id 공개 URL: https://danmeon.github.io/rhwp-python/schema/hwp_ir/v1/schema.json — 불변 경로 정책 (v1 영구). 외부 도구는 이 URL 또는 *.hwp_ir.json 파일명 convention 사용 가능.

미구현 블록 타입 (Picture / Formula / Footnote / ListItem / Caption / TocEntry / Field) 은 UnknownBlock catch-all 로 forward-compat — v0.3.0 에서 추가되어도 v0.2.0 소비자가 깨지지 않는다.

성능

Apple M2 (8 코어) release 빌드. Parse = 파일 읽기 + 전체 파싱 + Document 생성. 워크로드: 9 개 파일 (aift.hwp 5.5 MB + table-vpos-01.hwpx 359 KB + tac-img-02.hwpx 3.96 MB, ×3).

워커 수 Parse 시간 순차 대비 가속
1 268 ms 1.00× (기준)
2 141 ms 1.91×
4 97 ms 2.76×
8 67 ms 4.01×

parse() 와 PDF 변환 단계는 py.detach 로 GIL 을 해제하므로 ThreadPoolExecutor 가 코어 수에 비례해 스케일. PDF 렌더링 자체는 usvg + pdf-writer 내부에서 CPU/allocator 바운드라 2 ~ 3 워커에서 약 1.1× 정도만 향상됨 — 재현은 benches/bench_gil.py 참고.

알려진 제약 (Phase 1)

  • Document 객체는 #[pyclass(unsendable)] — 단일 스레드 접근만 허용. 교차 스레드 접근 시 RuntimeError. 멀티스레드에선 benches/bench_gil.py 패턴 사용 — 워커 내에서 parse + consume 까지 완결한 뒤 원시 타입(int, str, bytes) 만 반환.
  • 폰트 임베딩 / 디버그 오버레이 / 페이지 메타데이터 API 없음 (Phase 2+).
  • HWP/HWPX 저장(serialization) 미지원 — 읽기/렌더링 전용.
  • 표 / 이미지 / 수식 구조화 접근 없음 — 텍스트 추출만 지원.
  • PDF 렌더 경로가 rhwp 코어의 [DEBUG_TAB_POS] / LAYOUT_OVERFLOW 로그를 stdout 으로 출력. 필요 시 grep -v -E "(DEBUG_TAB_POS|LAYOUT_OVERFLOW)" 로 필터링.

개발

이 리포는 rhwp Rust 코어를 external/rhwp git submodule 로 소비합니다.

git clone --recurse-submodules https://github.com/DanMeon/rhwp-python
cd rhwp-python

# dev + testing + linting 툴 일괄 설치
uv sync --no-install-project --group all
uv run maturin develop --release

# 테스트 (core + LangChain, slow PDF 제외)
uv run pytest tests/ -m "not slow"

# PDF 렌더링 테스트
uv run pytest tests/ -m slow

# 타입 체크
uv run pyright python/ tests/

# GIL 해제 벤치마크
uv run python benches/bench_gil.py 2>&1 | grep -v -E "(DEBUG_TAB_POS|LAYOUT_OVERFLOW)"

clone 시 --recurse-submodules 를 빠뜨렸다면:

git submodule update --init --recursive

테스트 fixture 는 submodule 내부 external/rhwp/samples/ 에 있으며, tests/conftest.py 가 이 경로를 참조합니다.

버전 관리

이 Python 패키지와 rhwp Rust 코어는 독립적으로 버저닝됩니다. rhwp.version() 은 이 패키지 버전을, rhwp.rhwp_core_version() 은 고정된 submodule 에 포함된 Rust 코어의 버전을 반환합니다.

라이선스

MIT. 저작권자: Edward Kim (rhwp Rust 코어) + DanMeon (rhwp-python 바인딩). 자세한 내용은 LICENSE.

프로젝트 홈

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

rhwp_python-0.2.0.tar.gz (52.7 MB view details)

Uploaded Source

Built Distributions

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

rhwp_python-0.2.0-cp310-abi3-win_amd64.whl (3.3 MB view details)

Uploaded CPython 3.10+Windows x86-64

rhwp_python-0.2.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.3 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

rhwp_python-0.2.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.2 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

rhwp_python-0.2.0-cp310-abi3-macosx_11_0_arm64.whl (3.0 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

rhwp_python-0.2.0-cp310-abi3-macosx_10_12_x86_64.whl (3.2 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file rhwp_python-0.2.0.tar.gz.

File metadata

  • Download URL: rhwp_python-0.2.0.tar.gz
  • Upload date:
  • Size: 52.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rhwp_python-0.2.0.tar.gz
Algorithm Hash digest
SHA256 0f028feeff36467ec9f6b60d37d1bd5109cbbf749a20587f0b99af7b31f52ea7
MD5 fff891aa44a54110ace227896e2e0045
BLAKE2b-256 d0f140a94a5cb2364d65855792f15eac4e34acd2b4ea41465c056927eaaafe57

See more details on using hashes here.

Provenance

The following attestation bundles were made for rhwp_python-0.2.0.tar.gz:

Publisher: publish.yml on DanMeon/rhwp-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rhwp_python-0.2.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: rhwp_python-0.2.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 3.3 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rhwp_python-0.2.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 3213876ce016abf3a2ca9e0d357a61bf0178b6c8c23cdf89cf1c3c1ef77bb2f2
MD5 3b66935fb130db1db6d716927a645767
BLAKE2b-256 7d8ee0f007a2217b50f174881fb5bd277ba8525816789b5ef3e0fad6d3050fcb

See more details on using hashes here.

Provenance

The following attestation bundles were made for rhwp_python-0.2.0-cp310-abi3-win_amd64.whl:

Publisher: publish.yml on DanMeon/rhwp-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rhwp_python-0.2.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rhwp_python-0.2.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f9f1dcbba3c796498b4352320f8ce9cdb41a47481d69f7ac8fdf436b8d80e844
MD5 c5dbe02e5089a830a5f9c3b4e66aac35
BLAKE2b-256 63be9deea3125f31232607b0314bc55feb3f29899ce0596b014069718c86cd45

See more details on using hashes here.

Provenance

The following attestation bundles were made for rhwp_python-0.2.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on DanMeon/rhwp-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rhwp_python-0.2.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rhwp_python-0.2.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b5f091c99723b326ec55ffa230c89e746a5f5a7ad29ac673c0e186a5dde0e663
MD5 66ceca14bd129201cf6a4ba39c81c7d9
BLAKE2b-256 62f421249c10aa94bd8ae174a73a3c1ab3a53c8d602d10effe2582dfbb395359

See more details on using hashes here.

Provenance

The following attestation bundles were made for rhwp_python-0.2.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on DanMeon/rhwp-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rhwp_python-0.2.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rhwp_python-0.2.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e4c901e88b0b3cd7b7f6d70bb2e99b5175a87cf401024cd061de37649feb9fbe
MD5 120d3126d1ad47d2b51734773bebe885
BLAKE2b-256 9f688c567984d2761a771e00a89fd3bfdd49e9dd3be6eb72dae46fb836683ac6

See more details on using hashes here.

Provenance

The following attestation bundles were made for rhwp_python-0.2.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on DanMeon/rhwp-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rhwp_python-0.2.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for rhwp_python-0.2.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 38ea84afe6d7ae7398a3970afde6d93a3548b5f95803973a58ce50051ac048b1
MD5 23c14c6bf49f07316f7e1cacdcdfc698
BLAKE2b-256 9b532382185a229b15a4dedec8ad83484ab3a153335507223e489bc0bd84737f

See more details on using hashes here.

Provenance

The following attestation bundles were made for rhwp_python-0.2.0-cp310-abi3-macosx_10_12_x86_64.whl:

Publisher: publish.yml on DanMeon/rhwp-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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