ezsxf
A fast SXF parser and drawing converter for Python, implemented in Rust with PyO3.
ezsxf supports both SXF formats:
P21(ISO-10303-21 based)SFC(SXF feature blocks)
Status
The SFC parser covers all 34 feature types in the SXF Ver.3.1 SFC specification, including resolved drawing/compound-figure/composite-curve structure. The P21 reader currently exposes the generic Part 21 entity representation.
Features
- Parse
P21andSFCfrom file path, text, or bytes - Decode SFC files as UTF-8 or Windows Shift-JIS/CP932 without lossy replacement
- Strict and lenient parsing modes
- Structured parse output (
header,entities,typed_features,model,warnings) - Resolve layer/style code tables, compound-figure placements, and hatch boundaries
- Decode
ATRF/ATRU/ATRSattribute attachments separately from drawing groups - Validate compound-figure placement counts, hierarchy, and drawing-group transforms
- Convert SFC drawings to AutoCAD 2007 ASCII DXF without another runtime dependency
- Draw SFC drawings with the optional
matplotlibbackend - Python API + CLI (
ezsxf/python -m ezsxf)
Installation
From source (recommended currently)
python -m venv .venv
source .venv/bin/activate
pip install maturin
maturin develop
Install the plotting extra when using the matplotlib backend:
pip install ".[plot]"
Quick Start
import ezsxf
result = ezsxf.parse_sfc("./data/D0LS004ZSFC/D0LS004Z.SFC", strict=True)
print(result["format"]) # "sfc"
print(len(result["typed_features"]))
print(result["model"]["sheet"]["component_ids"])
Title-block (sheet) attribute names
SXF represents title-block information in two related places. The
drawing_attribute_feature stores the drawing-wide values and is returned in
typed_features with kind == "drawing_attribute". Text drawn in the title
block is linked to those values by an ATRS attribute attachment. By contrast,
drawing_sheet_feature (kind == "drawing_sheet") describes the paper size
and orientation; model["sheet"] is the resolved paper/container structure,
not the title-block metadata.
The following strings are the exact, machine-readable predefined attribute
names used in an ATRS attachment. They are case-sensitive literals and must
not be translated or replaced by the S-xx catalogue identifier. All eleven
attributes have the predefined SXF type STR.
| Catalogue ID | Exact attribute_name |
SFC field / Python key | Meaning |
|---|---|---|---|
S-05 |
表題_事業名 |
P_Name / project_name |
Project name |
S-06 |
表題_工事名 |
C_Name / construction_name |
Construction name |
S-07 |
表題_契約区分 |
C_type / contract_type |
Contract type |
S-08 |
表題_図面番号 |
D_number / drawing_number (before $$) |
Drawing number |
S-09 |
表題_図面総数 |
D_number / drawing_number (after $$) |
Total drawing count |
S-10 |
表題_図面種別 |
D_type / drawing_type |
Drawing type |
S-11 |
表題_尺度 |
D_Scale / drawing_scale |
Scale |
S-12 |
表題_図面名 |
D_title / drawing_name |
Drawing name |
S-13 |
表題_年月日 |
D_Year, D_Month, D_Day / drawing_year, drawing_month, drawing_day |
Drawing date |
S-14 |
表題_会社名 |
C_Contractor / contractor_name |
Contractor name |
S-15 |
表題_事務所名 |
C_Owner / owner_name |
Owner/commissioning organization name |
An explicit-type attachment name has this form:
$$ATRS$$<figure-id>$$<attribute-name>$$STR
For example, $$ATRS$$9$$表題_事業名$$STR is exposed at
model["attribute_attachments"][...]["attribute"] as:
{
"mechanism": "ATRS",
"figure_id": "9",
"attribute_name": "表題_事業名",
"attribute_type": "STR",
"unit": None,
}
Because ATRS applies to a text feature, that feature's displayed text is the
attribute value; there is no separate attribute_value key. The type and unit
may be omitted from the encoded name, in which case their parsed values are
None.
For a title-block value drawn on multiple lines, use the unsuffixed predefined
name for a single line. For multiple lines, the SXF specification's published
form appends an ASCII space and a 1-based ASCII line number, for example
表題_工事名 1 and 表題_工事名 2. ezsxf preserves this suffix verbatim and
does not fold the line-specific names back to the base name.
There are two compound-field rules to keep separate from the ATRS names:
D_number/drawing_numberstores<drawing-number>$$<total-count>when a total count is present, while title-block text uses separate表題_図面番号and表題_図面総数attachments.表題_年月日is one text attribute, whiledrawing_attribute_featureexposes its date as the three integer keysdrawing_year,drawing_month, anddrawing_day.
Convert the original input or an already parsed result to DXF:
ezsxf.to_dxf("./data/D0LS004ZSFC/D0LS004Z.SFC", "drawing.dxf")
parsed = ezsxf.parse_sfc("./data/D0LS004ZSFC/D0LS004Z.SFC")
dxf_text = ezsxf.to_dxf(parsed)
Draw with matplotlib and save through the returned Axes:
ax = ezsxf.plot("./data/D0LS004ZSFC/D0LS004Z.SFC")
ax.figure.savefig("drawing.png", dpi=200, bbox_inches="tight")
Both backends share the same hierarchy, placement, layer, color, line type,
line width, text, dimension, and hatch conversion. Curves are converted to
polylines; use curve_segments to control the approximation resolution.
Converters that need true curves can read PathPrimitive.curve
(CurveGeometry): for circle, arc, ellipse and elliptical-arc sources it holds
the exact curve behind the sampled points, already transformed through
compound-figure placements. The curve is center + axis_u*cos(t) + axis_v*sin(t)
for t from start_param to end_param; axis_u/axis_v are conjugate
semi-diameters, so a circle placed with unequal X/Y ratios is reported as the
ellipse it becomes.
Drawing conversion currently targets SFC input. Externally defined symbols are shown as insertion markers, while externally defined and tiled hatch patterns retain only boundaries marked visible by the SXF data.
CLI
# smoke test
python -m ezsxf
# parse to JSON
python -m ezsxf parse sfc ./data/D0LS004ZSFC/D0LS004Z.SFC --pretty
python -m ezsxf parse p21 ./data/D0LS004ZP21/D0LS004Z.P21 --lenient
# convert SFC to DXF
python -m ezsxf to-dxf ./data/D0LS004ZSFC/D0LS004Z.SFC drawing.dxf
# save or interactively display a matplotlib drawing
python -m ezsxf plot ./data/D0LS004ZSFC/D0LS004Z.SFC drawing.png --dpi 200
python -m ezsxf plot ./data/D0LS004ZSFC/D0LS004Z.SFC
Development
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
# Python-level tests
python -m unittest discover -s tests -p 'test_*.py' -v
Repository Layout
src/*.rs: Rust parser, resolved model, and PyO3 bindingssrc/ezsxf/: Python API, CLI, DXF writer, matplotlib backend, and stubsdata/: SXF sample datasets used for validation
License
MIT License. See LICENSE.
Metadata
Release files for ezsxf 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ezsxf-0.1.2.tar.gz | 79.3 kB | Details |
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ezsxf-0.1.2-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| ezsxf-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| ezsxf-0.1.2-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.9 | abi3 | macOS 10.12+ universal2 (ARM64, x86-64), macOS 11.0+ ARM64, macOS 10.12+ x86-64 | Details |
Total release size: 2.2 MB
Release files / ezsxf-0.1.2.tar.gz
| Download URL | ezsxf-0.1.2.tar.gz |
|---|---|
| Size | 79.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5f5c23c3cd5628745b991f2aef3d6a1dbff343883385704bea24045b83de119b
|
|
BLAKE2b-256 checksum How to use checksums |
589ab9066fb267b351fe140bfeb2eeeb041762035cb7a9bac610d2c6e94abc85
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / ezsxf-0.1.2-cp39-abi3-win_amd64.whl
| Download URL | ezsxf-0.1.2-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 462.6 kB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
5680778e771b7defd7b51bd7f982287356fc15a316b7e916b8f8961fe4b0392c
|
|
BLAKE2b-256 checksum How to use checksums |
f61107de614346eb85b2aeb52ff7bdef433cca7c873b2028d2667f5998ca8409
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / ezsxf-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | ezsxf-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 593.6 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
f6563822c6ccf742b244eaa487770d3936df3f790f10a0a8540f5805914cc9a0
|
|
BLAKE2b-256 checksum How to use checksums |
847e0ff41850dae0dff859983fd6d689012972240cb80d13a0709af7e6f93fc5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / ezsxf-0.1.2-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | ezsxf-0.1.2-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
0a4f62ce5016478344f8a67e19175489a4806c5e71fcfb742ec4849261eb7a69
|
|
BLAKE2b-256 checksum How to use checksums |
bf5190167429f2ffd4d816fcda637bb4155e93e0d1455b4a98429aaec9e6dc24
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency log