ezdwg
DWG (R13-R2018 / AC1012-AC1032) reader with a Python API inspired by ezdxf. This project is a DWG read-focused parser with growing high-level entity coverage while providing a native AC1015 writer for basic entities and nested blocks.
Documentation: https://monozukuri-ai.github.io/ezdwg/
Status
- High-level API (
ezdwg.read): R13 / AC1012 and R14 / AC1014 (2D entities), R2000 / AC1015, R2004 / AC1018, R2007 / AC1021, R2010 / AC1024, R2013 / AC1027, R2018 / AC1032 - Raw API (
ezdwg.raw): the same versions, with the per-typedecode_*functions and the table, style and placement functions - High-level entities include LINE, ARC, LWPOLYLINE, POINT, CIRCLE, ELLIPSE, TEXT, MTEXT, DIMENSION, INSERT/MINSERT, HATCH, and SPLINE
- Raw API exposes the corresponding entity decoders plus low-level POLYLINE/VERTEX helpers
- Output units/angles: high-level API returns ARC angles in degrees
Install
Install from PyPI:
pip install ezdwg
Plotting (optional):
pip install "ezdwg[plot]"
DWG to DXF conversion (optional, ezdxf backend):
pip install "ezdwg[dxf]"
If you want to contribute or develop locally, you can install from source: Rust toolchain is required (PyO3 build).
git clone https://github.com/monozukuri-ai/ezdwg.git
cd ezdwg
maturin develop
pip install -e .
For release version updates, run uv run scripts/bump_version.py <version>.
The root Cargo.toml is the single version source for Rust and Python; the
command refreshes the lock files. See Releasing for details.
Quick Start
import ezdwg
doc = ezdwg.read("path/to/file.dwg")
msp = doc.modelspace()
for e in msp.query(
"LINE LWPOLYLINE ARC CIRCLE ELLIPSE POINT TEXT MTEXT "
"DIMENSION INSERT MINSERT HATCH SPLINE"
):
print(e.dxftype, e.handle, e.dxf)
doc.modelspace() yields only model-space entities (block-definition contents and
paper-space entities are excluded via each entity's stored placement);
doc.paperspace() yields paper-space entities and doc.entities() everything in
the file, with e.dxf["owner_handle"] / doc.entity_placement(handle) to
partition them yourself.
Layouts and viewports:
import ezdwg
doc = ezdwg.read("path/to/file.dwg")
for name, layout in doc.layouts().items():
print(name, layout["model"], layout["active"], layout["paper_width"], layout["paper_height"])
for viewport in doc.paperspace().query("VIEWPORT"):
dxf = viewport.dxf
scale = dxf["height"] / dxf["view_height"] # R2000+; the first viewport of a sheet is the sheet itself
Drawing units and header variables:
import ezdwg
doc = ezdwg.read("path/to/file.dwg")
doc.units # "millimeters" ($INSUNITS; None for R14)
doc.header_variables()["extmin"] # model-space extents, unit formats, ...
Plot in matplotlib:
import ezdwg
doc = ezdwg.read("path/to/file.dwg")
doc.plot()
CLI
uvx ezdwg --version
uvx ezdwg inspect examples/data/line_2000.dwg
uvx ezdwg inspect examples/data/line_2000.dwg --verbose
uvx --from "ezdwg[plot]" ezdwg plot examples/data/line_2000.dwg
uvx --from "ezdwg[plot]" ezdwg plot examples/data/line_2000.dwg -o /tmp/line_2000.png --dpi 200
uvx --from "ezdwg[dxf]" ezdwg convert examples/data/line_2000.dwg /tmp/line_2000_out.dxf
uvx --from "ezdwg[dxf]" ezdwg convert examples/data/arc_2000.dwg /tmp/arc_2000_out.dxf --types "ARC" --dxf-version R2010
uvx ezdwg write examples/data/line_2000.dwg /tmp/line_2000_out.dwg --types "LINE" --dwg-version AC1015
plot displays model-space entities in a matplotlib window, or opens an SVG
preview in your browser when no interactive backend is available. Use -o / --output
to save a PNG, SVG, or PDF without opening a viewer; --types and --title
filter entities and set the title. For local development, run
uv run --extra plot ezdwg plot path/to/file.dwg.
DWG to DXF
ezdxf is used as the DXF writing backend.
import ezdwg
result = ezdwg.to_dxf(
"examples/data/line_2000.dwg",
"/tmp/line_2000_out.dxf",
types="LINE ARC LWPOLYLINE",
dxf_version="R2010",
)
print(result)
Or from an already opened document/layout:
doc = ezdwg.read("examples/data/line_2000.dwg")
doc.export_dxf("/tmp/line_2000_out.dxf")
DWG to DWG (Native AC1015 Writer)
import ezdwg
result = ezdwg.to_dwg(
"examples/data/line_2000.dwg",
"/tmp/line_2000_rewrite.dwg",
version="AC1015",
)
print(result)
Or from an already opened document/layout:
doc = ezdwg.read("examples/data/line_2000.dwg")
doc.export_dwg("/tmp/line_2000_rewrite.dwg", version="AC1015")
Path/Document exports select model space. Use strict=True to reject unsupported
or undecoded entities and detected attribute loss before writing. Otherwise inspect
result.skipped_by_type and result.diagnostics. Referenced layers, simple line
patterns, basic text styles, Japanese text, units and placement attributes are
preserved. Referenced blocks and attached attributes are kept as a graph. Complete
source document metadata remains outside the scope.
See native writer scope and external checks.
Create and Edit DWG
import ezdwg
drawing = ezdwg.new() # AC1015, no input file needed
msp = drawing.modelspace()
line = msp.add_line((0, 0), (10, 5), color_index=1)
msp.update(line, end=(20, 5))
drawing.save("created.dwg") # strict validation by default
edited = ezdwg.read("created.dwg").edit()
edited.modelspace().add_circle((5, 5), radius=2)
edited.save("edited.dwg")
The editable snapshot supports basic entities, block definitions, nested INSERTs
and single-line ATTDEF/ATTRIB attributes.
Queries return live entities; use update(), mutate entity.dxf, or call
delete(entity). Saving validates the drawing, writes a temporary sibling file,
and atomically replaces the destination. See the editing guide
for table editing, import limitations and diagnostics.
Blocks use the same geometry methods in local coordinates:
part = drawing.blocks.new("Part", base_point=(0, 0, 0))
part.add_circle((0, 0), radius=2)
part.add_attdef("ID", "default", insert=(0, 3), height=1)
ref = msp.add_blockref("Part", insert=(10, 20), rotation=30)
msp.add_attrib(ref, "ID", "P-001", insert=(10, 23), height=1)
drawing.save("blocks.dwg")
Attribute placement is explicit; add_attrib does not automatically transform an
ATTDEF or synchronize defaults. See blocks and attributes.
Examples
Sample DWG files are available under examples/data/.
python examples/basic_read.py
python examples/query_types.py
python examples/plot.py
python examples/text_mtext.py
python examples/dimensions.py
python examples/raw_insert_2004.py
python examples/convert_to_dxf.py
Low-Level API
If you need raw decode access:
from ezdwg import raw
raw.decode_line_entities("path/to/file.dwg")
Limitations
- Native DWG write currently targets AC1015 only
- Native DWG write supports a subset of entities: LINE/RAY/XLINE/POINT/ARC/CIRCLE/ELLIPSE/SPLINE/SOLID/TRACE/3DFACE/LWPOLYLINE/POLYLINE_2D/POLYLINE_3D/TEXT/MTEXT/INSERT/ATTDEF/ATTRIB/HATCH/DIMENSION/IMAGE, including nested block definitions, rendered dimension blocks and raster image definitions; true colours are rounded to the nearest ACI
- High-level API supports R13 (AC1012, experimental), R14 (AC1014, experimental), R2000 (AC1015), R2004 (AC1018), R2007 (AC1021), R2010 (AC1024), R2013 (AC1027), and R2018 (AC1032)
- AC1012/AC1014 decode the 2D entity types with the layouts of the ODA specification (LINE, ARC, CIRCLE, ELLIPSE, POINT, LWPOLYLINE, POLYLINE_2D, TEXT, MTEXT, ATTRIB/ATTDEF, INSERT/MINSERT, HATCH, SOLID, TRACE, 3DFACE, SPLINE, LEADER, TOLERANCE, MLINE, SHAPE, DIMENSION), with block membership, block names and dimension blocks, and the 3D polylines and meshes. R13/R14 have no lineweights and no layer plot flag, and their viewports state a window but no view
- AC1021/AC1024/AC1027/AC1032 use native decode for LINE/ARC/LWPOLYLINE/POINT/CIRCLE/ELLIPSE and are regression-tested against paired DXF samples
- TEXT/MTEXT/ATTRIB/ATTDEF of R2007 and later are read from the string stream of the object and regression-tested on one drawing saved in every version (R14 to R2018)
- AC1021/AC1024/AC1027/AC1032 entity style/layer color resolution is currently best-effort on some files
- Ordinary legacy 2D/3D polylines have native roundtrip tests and opt-in ODA import/export coverage for AC1015/AC1018/AC1027; fitted polylines and mesh writing remain unsupported
- ARC angles in raw API are radians (high‑level API converts to degrees)
Metadata
Release files for ezdwg 0.16.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 | |
|---|---|---|---|
| ezdwg-0.16.1.tar.gz | 454.6 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| ezdwg-0.16.1-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| ezdwg-0.16.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| ezdwg-0.16.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| ezdwg-0.16.1-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.10 | abi3 | macOS 10.12+ universal2 (ARM64, x86-64), macOS 11.0+ ARM64, macOS 10.12+ x86-64 | Details |
Total release size: 8.4 MB
Release files / ezdwg-0.16.1.tar.gz
| Download URL | ezdwg-0.16.1.tar.gz |
|---|---|
| Size | 454.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
11d534ef5ba15024fbd2235099872159cde360a6f4b999905c816cfee5f7942a
|
|
BLAKE2b-256 checksum How to use checksums |
dfc07051220f098a76abff7e48fb13a01a0c925e21c6b97dc3616495b3d04a35
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","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}
|
Release files / ezdwg-0.16.1-cp310-abi3-win_amd64.whl
| Download URL | ezdwg-0.16.1-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
d286b0bb1148e906dadc221425b70df1aaf9f3cee689791596e0e4f775331a88
|
|
BLAKE2b-256 checksum How to use checksums |
40dc3d049d30f3db8ddcda55c409671183a8acea96de5fc8d24bc092dcff5a91
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","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}
|
Release files / ezdwg-0.16.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | ezdwg-0.16.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
3030832c0eff641a27b810301b46186a599338a798100d131dfdc980205dd468
|
|
BLAKE2b-256 checksum How to use checksums |
76b7299c5163c337d218410e7a03e8bbe92c3391dd8d45f257566356d5484649
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","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}
|
Release files / ezdwg-0.16.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | ezdwg-0.16.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
829ee2e938cc1b4bd9838cef403efe4b580cb1b5a17b7095dfb544a28a9a0d24
|
|
BLAKE2b-256 checksum How to use checksums |
ab9ea79c06c73a78e6aeb37eb389d6bb16c81120b4997794b69898c3aafb9d59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","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}
|
Release files / ezdwg-0.16.1-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | ezdwg-0.16.1-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.10 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
707adc9ccca598e8ca1bd79d3f008d401e7d215e663c54908d8bc438d9b4f76a
|
|
BLAKE2b-256 checksum How to use checksums |
72c572752aa86a740ceea58c799eee8c22ff8566b56d87cca39236c4718e9fbb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","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}
|