model wraps the active document with a small, Pythonic API for the things scripts do most:
dimensions, global variables, custom properties, rebuild control, mass properties and finding faces
and edges. For
everything else, model.doc is the full SOLIDWORKS API (chapter 5).
The examples assume a part like the one the test suite uses: a 100 × 60 × 20 mm block
(Boss-Extrude1) with a Ø20 mm cylinder (Boss-Extrude2) standing on it.
model # <Model 'Part1'>
model.title # 'Part1' - the window titleFor a document that is not active, wrap it yourself: Model(other_doc). To create geometry, assemblies
and drawings, see Building models.
Dimensions are addressed by their full name, "<dimension>@<feature or sketch>", and values are SI:
depth = model.dims["D1@Boss-Extrude1"] # 0.02
print(to(depth, mm), "mm")
model.dims["D1@Boss-Extrude1"] = 25 * mm # updates and rebuilds
print(round(to(model.dims["D1@Boss-Extrude1"], mm), 6))
model.dims["D1@Boss-Extrude1"] = 20 * mm| Expression | Result |
|---|---|
model.dims[name] |
Value in SI units (m, or rad for angles). KeyError if the name does not exist |
model.dims[name] = value |
Set (SI) and rebuild - unless inside model.batch() |
name in model.dims |
Whether the dimension exists |
model.dims.names() |
Names of all displayed dimensions |
model.dims.items() |
{name: value} for all of them |
for name, value in model.dims.items().items():
print(f"{name:24} {to(value, mm):8.2f} mm")Finding a name: in SOLIDWORKS, select a dimension and look at the Primary Value box of the
PropertyManager (e.g. D1@Boss-Extrude1), or print model.dims.names().
model.globals reads and writes the global variables of the equation manager:
model.globals["Width"] = 120 * mm # creates or updates "Width" = 120mm
print(model.globals["Width"]) # 0.12 (SI)
model.globals["Count"] = 4 # int -> unitless number
print(model.globals.items())
del model.globals["Count"]| Write | Stored as |
|---|---|
float (e.g. 120 * mm) |
A length in mm - or in the variable's existing unit (in, deg ...) |
int |
A plain number |
str |
A raw expression, e.g. '"Width" / 2' |
Reading returns SI when the expression is a number with a unit (120mm -> 0.12), otherwise the
evaluated number (as float).
To let a global drive a dimension, add an equation through the API:
model.globals["Thick"] = 20 * mm
model.doc.GetEquationMgr().Add2(-1, '"D1@Boss-Extrude1" = "Thick"', True)
model.rebuild()
model.globals["Thick"] = 30 * mm # the block follows
print(round(to(model.dims["D1@Boss-Extrude1"], mm), 6)) # 30.0
model.globals["Thick"] = 20 * mmEvery dims[...] = and globals[...] = rebuilds immediately. When you change many values, wrap
them in model.batch(): graphics and the FeatureManager tree are frozen and the model rebuilds
once at the end. Batches can be nested.
with model.batch():
model.globals["Width"] = 110 * mm
model.globals["Thick"] = 22 * mm
model.globals["Thick"] = 20 * mmmodel.batch(rebuild=False) skips the final rebuild. model.rebuild() rebuilds changed features;
model.rebuild(force=True) rebuilds everything.
props = model.mass
print(props["mass"], "kg")
print(to(props["volume"], mm**3), "mm^3")
print(props["center"]) # Vec(x, y, z) in metresKeys: mass (kg), volume (m³), area (m²), center (Vec, m), density (kg/m³). The values
come from the material and density set in the document (or its template).
model.props works like a dictionary of the document's custom properties. The property type follows
the Python value: str → Text, int/float → Number, bool → Yes or no, datetime.date → Date.
import datetime
model.props["PartNo"] = "P-1001"
model.props["Quantity"] = 4
model.props["Purchased"] = False
model.props["Released"] = datetime.date(2026, 10, 8)
model.props.link("Weight", "SW-Mass") # linked to a system property (or a dimension name)
for name, value in model.props.items().items():
print(f"{name:10} {value:12} {model.props.kind(name)}")
print(model.props.raw("Weight")) # '"SW-Mass@Part1.SLDPRT"' - the stored expression
del model.props["Quantity"]Reading always gives the resolved value as a string, the way SOLIDWORKS shows it in the
Evaluated Value column ("Yes", "2026-10-08", "127.85"); raw(name) gives the text expression.
Names are case-insensitive. Missing names raise KeyError, and the usual dictionary methods work
(in, get, update, pop, len, iteration).
set(name, value, kind) forces a type: model.props.set("Code", 42, "text"). Changing the type of
an existing property moves it to the end of the list (SOLIDWORKS deletes and re-adds it).
Configuration-specific properties (parts and assemblies) live under config(name):
active = model.doc.ConfigurationManager.ActiveConfiguration.Name
model.props.config(active)["Finish"] = "Anodized"
print(model.props.config(active)) # Props[Default]({'Finish': 'Anodized'})Notes: SOLIDWORKS keeps at most 6 decimals of a decimal number in the expression (the evaluated value
keeps what you wrote), and a linked system property such as SW-Mass is evaluated in the document's
units (grams with the default part template).
for f in model.features(): # tree order, including hidden system features
print(f.GetTypeName2(), f.Name)
boss = model.feature("Boss-Extrude1") # by name, None if missing
print(boss.Name, boss.GetTypeName2())model.planes returns the three default planes by position, so scripts also work with templates
that rename them (XY PLANE, Plan de face ...):
front, top, right = model.planes
print(model.planes.front.Name, model.planes.top.Name, model.planes.right.Name)
model.planes.top.Select2(False, 0)model.faces and model.edges return queries: lists you can filter with chainable methods.
Each item is an IFace2 / IEdge, so the whole API is available on it.
faces = model.faces
print(len(faces), "faces,", len(faces.planar()), "planar,", len(faces.cylindrical()), "cylindrical")
top = faces.normal(Z) # planar faces whose outward normal is +Z
pin = faces.radius(10 * mm) # cylindrical faces of radius 10 mm
biggest = faces.planar().largest()
print(round(to(biggest.GetArea(), mm**2)), "mm^2")
vertical = model.edges.parallel(Z) # straight edges along Z
print(len(vertical), "vertical edges")| Query | Keeps |
|---|---|
faces.planar() / faces.cylindrical() |
Flat / cylindrical faces |
faces.normal(direction, tol=1e-6) |
Planar faces whose outward normal points along direction |
faces.radius(r, tol=1e-9) |
Cylindrical faces with radius r |
faces.area(lo, hi) |
Faces with lo <= area <= hi (m²) |
faces.edges |
All edges of these faces (each once) |
edges.linear() / edges.circular() |
Straight / circular edges |
edges.parallel(direction, tol=1e-6) |
Straight edges parallel to direction (either sense) |
edges.radius(r, tol=1e-9) |
Circular edges with radius r |
edges.length(lo, hi) |
Edges with lo <= length <= hi (m) |
q.where(predicate) |
Items for which predicate(item) is true |
q.largest() / q.smallest() |
Biggest / smallest item (area or length), None if empty |
q.sort(key=None, reverse=False) |
Sorted copy (default: by size) |
q.select(append=False) |
Select the items in the viewport; returns how many were selected |
Every filter returns a new query, so they chain:
model.faces.normal(Z).largest().Select4(False, None) # one face, raw API
n = model.faces.cylindrical().edges.circular().select() # all circular edges of the pin
print(n, "edges selected")where takes any function - use the raw API inside:
small = model.faces.where(lambda f: f.GetArea() < 1000 * mm**2)
print(len(small), "faces smaller than 1000 mm^2")Vec is a tuple of three floats with a little arithmetic: -v, v.dot(w), v.length, v.unit(),
v.angle(w) (radians). X, Y, Z are the unit axes, and API arrays convert directly:
n = Vec(model.faces.normal(Z)[0].Normal)
print(n, n.length, to(Vec(1, 1, 0).angle(X), deg))model.bodies() returns the solid bodies of a part (IBody2); model.bodies(solid=False) the
surface bodies.
for body in model.bodies():
print(body.Name, len(body.GetFaces()), "faces")