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.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 | |
|---|---|---|---|
| ezdwg-0.16.2.tar.gz | 456.7 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| ezdwg-0.16.2-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| ezdwg-0.16.2-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.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| ezdwg-0.16.2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64 | Details |
Total release size: 8.4 MB
Release files / ezdwg-0.16.2.tar.gz
| Download URL | ezdwg-0.16.2.tar.gz |
|---|---|
| Size | 456.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
36837cd35cbf8d47a9431726dc7fae1546a88d46539665e2f0d2d0766637bea7
|
|
BLAKE2b-256 checksum How to use checksums |
f0a1c48f61f34452370b0254f873855d9feca6fa052f02c02a3eb2b6ce4f4936
|
| 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.2-cp310-abi3-win_amd64.whl
| Download URL | ezdwg-0.16.2-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
c9a5af47d0e400b5c827e76859f72846c459a937b77abfb0dcdb7f4e22562eca
|
|
BLAKE2b-256 checksum How to use checksums |
4d8f7d760e8f396886e84631f6edc6ebb94a8703e6cf7b06434f0663b9be91ee
|
| 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.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | ezdwg-0.16.2-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 |
cc39fa5234ac0ae2f61b07bb111efd9dcb8b4857ff7f4d0807ae0788a1b979f5
|
|
BLAKE2b-256 checksum How to use checksums |
8ef45374583091239e2166c2617bbc0d88e2a43848064b9a9dac0c4819dafcad
|
| 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.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | ezdwg-0.16.2-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 |
3439f33cc257251d4f740427ec5e8ed2619718f2deeb0441506517a48b608da1
|
|
BLAKE2b-256 checksum How to use checksums |
d8cfe3c0ffa2077f2682aabbcbc9eb8795cf6cec8dcd38df785f1910752818b6
|
| 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.2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | ezdwg-0.16.2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 3.1 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 |
aea63c18a3fa162cb3dc2cd8896072e745f79f5f0933aeafb6918c2f688a52df
|
|
BLAKE2b-256 checksum How to use checksums |
2cfdf24f9e9d5a13ecdaf46200352e1d5341649535bcd5856e3a852a6c6b1ac4
|
| 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}
|