Blog · DXF · 1 Oct 2026 · 3 min read

How to merge DXF files with Python and ezdxf without losing dimensions

Combining DXF files with ezdxf looks like a copy loop. Then dimensions disappear, blocks go missing, units turn into metres and the audit says zero errors. The traps we hit when an AI agent merged drawings into client files, and the rule for each.

Short answer: do not use ezdxf.addons.Importer for drawings with dimensions, do not pass DIMENSION or INSERT entities to add_foreign_entity, and copy block definitions together with their inserts. Set the units of a new file to millimetres. Then check the result in a CAD program and as an image: ezdxf's audit is not a test.

The traps, one by one

Trap What happens Rule
ezdxf.addons.Importer Loses the DIMENSION entities Copy entities and their resources yourself
add_foreign_entity with DIMENSION or INSERT They vanish, no error Copy those with their blocks and styles
add_foreign_entity copies by default (copy=True) Transforming the source afterwards does nothing: 35 cells landed at the source coordinates, with "0 errors" Transform the copy it returns
entity.copy() on an INSERT Copies the reference, not the block definition Copy the BLOCK too
DIMENSION.transform() Does not enter the *D block, whose geometry is in absolute coordinates Transform the block content as well
add_entity with a dimension Renames its block (*D6606 becomes *D1) Do not rely on *D names
ezdxf.new() Sets units to metres ($INSUNITS=6) Set $INSUNITS to 4 (millimetres)
Filtering by layer Drops real content on layer 0: 14 machining notes lost, report said "done: 37, 0 problems" Select by what the entity is, not by layer
Re-importing into the same file "blocks added: 0" on a re-import means the old ones are still there Delete the entities, then the blocks, then import
Finding "what is ours" by coordinates Moves or deletes the wrong things Use a name prefix plus layer
Taking the sheet border from the leftmost geometry Wrong frame Use $EXTMIN / $EXTMAX
The target DXF is open in a CAD program PermissionError: [WinError 32] Close it first

Units: the one that multiplies by 1000

ezdxf.new() declares metres. 120 cells out of 136 came out declared in metres. Inserted into a drawing with automatic scaling, they were multiplied by 1000. One line fixes it:

doc = ezdxf.new()
doc.header["$INSUNITS"] = 4      # millimetres

Missing blocks that only CAD sees

ezdxf's audit reported 0 errors. BricsCAD reported Empty Record name: <AcDbBlockReference>. The cause: inserts copied without their block definitions. What caught it was a raw text count of the DXF: 12 occurrences of AcDbBlockReference, 0 of BLOCK.

A simple check the agent can run after every merge: every block name used by an INSERT must exist in doc.blocks.

used = {e.dxf.name for e in doc.modelspace().query("INSERT")}
missing = sorted(n for n in used if n not in doc.blocks)
print("missing blocks:", missing or "none")

Names: styles and blocks collide

When drawings are merged, two resources with the same name and different content become one. That moves dimensions and swaps sections between sheets. These two have their own guides:

How to check a merged file

  1. Open it in a CAD program, not only in ezdxf.
  2. Count by type per source sheet, before and after: dimensions, inserts, texts.
  3. Check every insert draws inside its own sheet frame.
  4. Render it to an image and look. See how to let an AI see a DXF.

Do and don't

Do

Don't

Questions people ask

Which ezdxf version is this? ezdxf 1.4.4 on Python 3.14.

Why not just paste in AutoCAD or BricsCAD? For one sheet, do. For dozens of sheets merged the same way every time, a script is repeatable and can check itself, as long as it checks the right things.