Python library for the SolidCAM Automation COM API
Project description
solidcam-api
A fully-typed Python library for the SolidCAM Automation COM API (scautom.dll).
solidcam-api wraps every section of the SolidCAM Automation API — General, CAD, CAM, Machine,
Part, Operation, Tool, Geometry, and Templates — in a clean, Pythonic interface with:
- Full type annotations and a
py.typedmarker (PEP 561) - Frozen dataclasses for all result objects
IntEnumconstants for all integer codes- A context-manager-friendly client
- Dependency injection / mock support for unit testing without SolidCAM
Platform note — SolidCAM is a Windows application.
The COM layer is only active on Windows; the package can be imported on any OS for documentation builds, static analysis, and testing with mocks.
Table of Contents
- Requirements
- Installation
- Quick start
- Usage examples
- API overview
- Error handling
- Testing without SolidCAM
- Contributing
- License
Requirements
| Requirement | Version |
|---|---|
| Python | ≥ 3.13 |
| pywin32 | ≥ 307 (Windows only) |
| SolidCAM | any version with scautom.dll registered |
Before using the library, the SolidCAM COM server must be registered:
regsvr32 "C:\Program Files\SolidCAM\scautom.dll"
This is done automatically by the SolidCAM installer.
Installation
pip install solidcam-api
With development tools (linting, type checking, tests):
pip install "solidcam-api[dev]"
With documentation build dependencies:
pip install "solidcam-api[docs]"
Quick start
from solidcam_api import SolidCAMClient
with SolidCAMClient() as sc:
sc.start_application(r"C:\Program Files\SolidWorks\SLDWORKS.exe")
sc.open(r"C:\CAM\my_part.prz")
sc.calculate()
sc.generate_gcode()
sc.close()
Usage examples
Open a part and generate G-code
from solidcam_api import SolidCAMClient
with SolidCAMClient() as sc:
# Start host CAD (SolidWorks) — wait for plugin to initialise
sc.start_application(r"C:\Program Files\SolidWorks\SLDWORKS.exe")
# Open a CAM part (no reference-model replacement)
sc.open(r"D:\jobs\bracket.prz")
# Check current part info
print(sc.part_path) # D:\jobs\bracket.prz
print(sc.part_type) # PartType.MILLING
print(sc.reference_model) # D:\cad\bracket_v3.sldprt
# Synchronise, calculate all operations, write G-code
sc.synchronize()
sc.calculate()
sc.generate_gcode()
# Save to a delivery folder
saved_path = sc.save(r"D:\output")
print(f"Saved to {saved_path}")
sc.close()
Change the reference model and recalculate
from solidcam_api import SolidCAMClient
with SolidCAMClient() as sc:
sc.start_application(r"C:\Program Files\SolidWorks\SLDWORKS.exe")
sc.open(r"D:\jobs\bracket.prz")
# Swap in the new revision of the CAD model
sc.change_reference_model(r"D:\cad\bracket_v4.sldprt")
sc.synchronize()
sc.calculate()
sc.generate_gcode()
sc.close()
List machines, operations, and tools
from solidcam_api import SolidCAMClient
with SolidCAMClient() as sc:
sc.start_application(r"C:\Program Files\SolidWorks\SLDWORKS.exe")
sc.open(r"D:\jobs\bracket.prz")
# --- Machines ---
print(f"Available machines ({sc.machine_count}):")
for machine in sc.list_machines():
print(f" [{machine.index}] {machine.name}")
print(f"Current machine: {sc.current_machine_name}")
# --- Operations ---
print(f"\nOperations ({sc.operation_count}):")
for op in sc.list_operations():
print(f" [{op.index}] {op.name!r:30s} type={op.type}")
# Suppress a roughing pass for a quick finish-only run
sc.suppress_operation("Roughing_1", suppress=True)
# --- Tools ---
print(f"\nTools ({sc.tool_count}):")
for tool in sc.list_tools():
print(f" [{tool.index}] {tool.name!r:25s} type={tool.type}")
sc.close()
Create stock and target geometry
from solidcam_api import SolidCAMClient, StockDefineBy, TargetDefineBy
with SolidCAMClient() as sc:
sc.start_application(r"C:\Program Files\SolidWorks\SLDWORKS.exe")
sc.open(r"D:\jobs\new_part.prz")
# Create a box stock with 2 mm offsets on every face
sc.create_stock_box(
name="Stock_Box",
x_plus=2.0, x_minus=2.0,
y_plus=2.0, y_minus=2.0,
z_plus=2.0, z_minus=0.0, # no offset on the bottom face
define_by=StockDefineBy.SOLID,
generate_stock_envelope=True,
)
# Create a cylindrical stock for a turning part
sc.create_stock_cylinder(
name="Bar_Stock",
right=3.0,
left=3.0,
external_diameter=2.0,
define_by=StockDefineBy.SOLID,
)
# Create a target from the finished solid
sc.create_target(
name="Finished_Part",
define_by=TargetDefineBy.SOLID,
generate_envelope=True,
)
# Inspect resulting geometry entries
for geom in sc.list_geometries():
print(geom.name)
sc.close()
Apply a process template
from solidcam_api import SolidCAMClient
with SolidCAMClient() as sc:
sc.start_application(r"C:\Program Files\SolidWorks\SLDWORKS.exe")
sc.open(r"D:\jobs\new_part.prz")
# List available process templates
for pt in sc.list_process_templates():
print(pt.name)
# Instantiate a process template against an existing geometry
sc.create_jobs_from_process_template(
process_template_name="Finish_Profile_Template",
geometry_name="Finished_Part",
sub_machine_index=1,
)
sc.calculate()
sc.generate_gcode()
sc.close()
Generate a tool sheet
from solidcam_api import SolidCAMClient
with SolidCAMClient() as sc:
sc.start_application(r"C:\Program Files\SolidWorks\SLDWORKS.exe")
sc.open(r"D:\jobs\bracket.prz")
# Discover available templates
print(sc.list_tool_sheet_names())
# e.g. ['Sheet_Full_HTML', 'Sheet_Full_RTF', ...]
sc.generate_tool_sheet("Sheet_Full_HTML")
sc.close()
API overview
All methods and properties are available directly on SolidCAMClient.
Connection lifecycle
| Member | Description |
|---|---|
SolidCAMClient(prog_id, *, com_object) |
Initialise (no COM connection yet) |
.connect() |
Create the COM dispatch object |
.disconnect() |
Release the COM dispatch object |
.is_connected |
True if the COM object is held |
with SolidCAMClient() as sc: |
Preferred: auto connect/disconnect |
General
| Member | Description |
|---|---|
.last_error |
Last error code (0 = no error) |
.last_error_description |
Human-readable last error message |
.log_file |
Path to the API log file (get/set) |
.pid |
Process ID of the target SolidCAM instance (get/set) |
.is_solidcam_running() |
True if SolidCAM process is active |
.start_application(path, wait_for_plugin) |
Start SolidWorks or standalone SolidCAM |
.start_solidcam() |
Start SolidCAM plugin (SolidWorks must be running) |
CAD
| Member | Description |
|---|---|
.open_host_file(path) |
Open a CAD file in the host |
.is_active_doc_cam_part |
True if the active document is a CAM part |
.render_preview(path) |
Generate a PDM preview image |
CAM
| Member | Description |
|---|---|
.open(part_path, model_path) |
Open a CAM part; optionally replace reference model |
.check_synchronization() |
Check sync status |
.synchronize() |
Synchronise the CAM part with its reference model |
.calculate(only_not_calculated) |
Calculate all (or only outdated) operations |
.calculate_operations(operations, only_not_calculated) |
Calculate a list of named operations |
.calculate_single_operation(number) |
Calculate one operation by number |
.change_post_processor_directory(path) |
Change the post-processor directory |
.generate_gcode() |
Generate G-code for the entire part |
.save(folder) |
Save to folder; returns the saved file path |
.save_as(path) |
Save to a new file path |
.save_to_folder(folder) |
Save to folder; returns the saved file path |
.close() |
Close the currently open CAM part |
.exit() |
Close SolidCAM entirely |
Machine
| Member | Description |
|---|---|
.machine_count |
Number of available machines |
.current_machine |
Index of the active machine (get/set) |
.current_machine_name |
Name of the active machine |
.get_machine_name(index) |
Name of machine at index |
.list_machines() |
list[Machine] of all machines |
Part
| Member | Description |
|---|---|
.part_path |
Path to the currently open CAM part |
.part_type |
PartType of the open part |
.reference_model |
Path to the reference CAD model |
.change_reference_model(model_path) |
Replace the reference model |
.create_new_part(name, path, part_type, machine_index, home_origin_position, inch) |
Create a new CAM part |
Operation
| Member | Description |
|---|---|
.operation_count |
Number of NC operations |
.number_of_jobs_with_exclamation_sign |
Count of operations with warnings |
.get_operation_name(index) |
Name of operation at index |
.get_operation_type(index) |
Raw type code of operation at index |
.get_operation(index) |
Operation dataclass at index |
.list_operations() |
list[Operation] of all operations |
.suppress_operation(name, suppress) |
Suppress or unsuppress a named operation |
.generate_gcode_for_operation(name, file_name) |
G-code for one operation |
Tool
| Member | Description |
|---|---|
.tool_count |
Number of tools in the tool table |
.tool_sheet_count |
Number of tool-sheet templates |
.get_tool_name(index) |
Name of tool at index |
.get_tool_type(index) |
Raw type code of tool at index |
.get_tool_tag(number, position, station, turret) |
Unique tool tag by address |
.get_tool(index) |
Tool dataclass at index |
.list_tools() |
list[Tool] of all tools |
.set_operation_tool(operation_name, tool_tag) |
Assign a tool to an operation |
.get_operation_tool_tag(operation_name) |
Tag of the tool used by an operation |
.get_tool_sheet_name(index) |
Name of tool-sheet template at index |
.list_tool_sheet_names() |
list[str] of all template names |
.generate_tool_sheet(template_name) |
Generate a tool sheet |
Geometry
| Member | Description |
|---|---|
.cad_coord_sys_count |
Number of CAD coordinate systems |
.get_cad_coord_sys_name(index) |
Name of CAD coord sys at index |
.get_cad_coord_sys(index) |
CoordSys at index |
.list_cad_coord_sys() |
list[CoordSys] |
.home_count |
Number of home positions |
.get_home_name(index) |
Name of home at index |
.get_home(index) |
HomeEntry at index |
.list_home_positions() |
list[HomeEntry] |
.create_home(home_origin_position) |
Create a home at a given origin |
.create_home_by_cad(cad_home_name) |
Create a home from a CAD coord sys |
.geom_count |
Number of geometry entries |
.get_geom_name(index) |
Name of geometry entry at index |
.get_geom(index) |
GeomEntry at index |
.list_geometries() |
list[GeomEntry] |
.create_target(...) |
Create a target solid geometry |
.create_stock_box(...) |
Create a box stock geometry |
.create_stock_cylinder(...) |
Create a cylindrical stock geometry |
Templates
| Member | Description |
|---|---|
.template_count |
Number of operation templates |
.get_template_name(index) |
Name of template at index |
.get_template(index) |
TemplateEntry at index |
.list_templates() |
list[TemplateEntry] |
.create_job_from_template(name, geometry, sub_machine, index) |
Instantiate one operation |
.process_template_count |
Number of process templates |
.get_process_template_name(index) |
Name of process template at index |
.get_process_template(index) |
ProcessTemplateEntry at index |
.list_process_templates() |
list[ProcessTemplateEntry] |
.create_jobs_from_process_template(name, geometry, sub_machine, index) |
Instantiate all operations |
Error handling
All API methods raise SolidCAMAPIError on failure. The exception carries three
attributes: method (the API call that failed), code (the integer error code from
LastError), and description (the human-readable description from LastErrorDescription).
from solidcam_api import SolidCAMClient, SolidCAMAPIError, SolidCAMConnectionError
try:
with SolidCAMClient() as sc:
sc.start_application(r"C:\Program Files\SolidWorks\SLDWORKS.exe")
sc.open(r"D:\jobs\bracket.prz")
sc.calculate()
sc.generate_gcode()
sc.close()
except SolidCAMConnectionError as exc:
print(f"Could not connect to SolidCAM: {exc}")
except SolidCAMAPIError as exc:
print(f"API call '{exc.method}' failed (code {exc.code}): {exc.description}")
Exception hierarchy
SolidCAMError
├── SolidCAMConnectionError # COM object could not be created
├── SolidCAMNotRunningError # SolidCAM process not detected
├── SolidCAMNotOpenError # No CAM part is currently open
└── SolidCAMAPIError # A specific API call returned failure
.method – str
.code – int
.description – str
Testing without SolidCAM
SolidCAMClient accepts a com_object keyword argument so you can inject a mock and test
automation scripts without a SolidCAM installation.
import unittest.mock as mock
from solidcam_api import SolidCAMClient, PartType
def test_calculate_called_after_open():
fake_com = mock.MagicMock()
fake_com.LastError = 0
fake_com.Open.return_value = 1
fake_com.Type = int(PartType.MILLING)
sc = SolidCAMClient(com_object=fake_com)
assert sc.is_connected
sc.open(r"C:\parts\test.prz")
sc.calculate()
fake_com.Open.assert_called_once_with(r"C:\parts\test.prz", "")
fake_com.Calculate.assert_called_once_with(False)
Contributing
- Fork the repository and create a feature branch.
- Install development dependencies:
pip install -e ".[dev]"
- Make your changes and add tests under
tests/. - Lint and format:
ruff check src tests ruff format src tests
- Type-check:
mypy src - Run tests:
pytest --cov=solidcam_api --cov-report=term-missing
- Open a pull request describing the change.
Project structure
solidcam-api/
├── src/
│ └── solidcam_api/
│ ├── __init__.py # Public API surface
│ ├── py.typed # PEP 561 marker
│ ├── _com.py # Internal COM wrapper (win32com)
│ ├── client.py # SolidCAMClient — assembles all sections
│ ├── exceptions.py # Exception hierarchy
│ ├── enums.py # IntEnum constants (PartType, OperationType, …)
│ ├── models/ # Frozen dataclasses for result objects
│ │ ├── machine.py
│ │ ├── operation.py
│ │ ├── tool.py
│ │ ├── geometry.py
│ │ └── template.py
│ └── sections/ # Section mixins (one per API section)
│ ├── _base.py
│ ├── general.py
│ ├── cad.py
│ ├── cam.py
│ ├── machine.py
│ ├── part.py
│ ├── operation.py
│ ├── tool.py
│ ├── geometry.py
│ └── template.py
├── tests/
├── pyproject.toml
└── README.md
License
MIT © 0ndrec
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file solidcam_api-0.1.0.tar.gz.
File metadata
- Download URL: solidcam_api-0.1.0.tar.gz
- Upload date:
- Size: 26.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5332133a043d24a7326176ec78775978061cb3319b5445d26963b9834294b2c8
|
|
| MD5 |
9de64964910d1f2420f9c7ba7890ca64
|
|
| BLAKE2b-256 |
9165ff8857218e23583738393874c04f8a5877cf325078583c05ec6c5b2a2719
|
File details
Details for the file solidcam_api-0.1.0-py3-none-any.whl.
File metadata
- Download URL: solidcam_api-0.1.0-py3-none-any.whl
- Upload date:
- Size: 37.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac3e60ecc9ba44ba543816f55cde500c8e355bfd3346afea94f2c1c528a7c522
|
|
| MD5 |
cb733e47b31a628529d7ac2e89acf788
|
|
| BLAKE2b-256 |
d4e6421c7a521cfff2086d8ebe77cd9dc16f9ac637f11339629d00eea9bade80
|