Examples
This section provides practical examples of using KiCadFiles in real-world scenarios.
Basic Usage Examples
Parsing KiCad Files
from kicadfiles import (
KicadPcb, KicadSch, Footprint, KicadSymbolLib, KicadWks,
KicadProject, KiCadDesignRules, FpLibTable, SymLibTable,
ParseStrictness
)
# Parse a PCB file
pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.STRICT)
print(f"Board has {len(pcb.footprints)} footprints")
# Parse a schematic file
schematic = KicadSch.from_file("tests/fixtures/schematic/minimal.kicad_sch", ParseStrictness.STRICT)
symbol_count = len(schematic.lib_symbols.symbols) if schematic.lib_symbols else 0
print(f"Schematic has {symbol_count} symbols")
# Parse a footprint file
footprint = Footprint.from_file("tests/fixtures/footprints/small.kicad_mod", ParseStrictness.STRICT)
print(f"Footprint has {len(footprint.pads)} pads")
# Parse a symbol library file
symbol_lib = KicadSymbolLib.from_file("tests/fixtures/symbols/small.kicad_sym", ParseStrictness.STRICT)
print(f"Library has {len(symbol_lib.symbols)} symbols")
# Parse a worksheet/template file
worksheet = KicadWks.from_file("tests/fixtures/worksheets/small.kicad_wks", ParseStrictness.STRICT)
print(f"Worksheet loaded successfully")
# Parse a project file (JSON format)
project = KicadProject.from_file("tests/fixtures/projects/minimal.kicad_pro", ParseStrictness.STRICT)
print(f"Project loaded successfully")
# Parse design rules file
design_rules = KiCadDesignRules.from_file("tests/fixtures/design_rules/minimal.kicad_dru", ParseStrictness.STRICT)
print(f"Design rules loaded")
# Footprint library table
fp_lib_table = FpLibTable.from_file("tests/fixtures/tables/fp-lib-table", ParseStrictness.STRICT)
print(f"Footprint library tables loaded")
# Symbol library table
sym_lib_table = SymLibTable.from_file("tests/fixtures/tables/sym-lib-table", ParseStrictness.STRICT)
print(f"Symbol library tables loaded")
Creating Objects Programmatically
from kicadfiles import At, Size, ParseStrictness
# Create basic objects programmatically
position = At(x=10.0, y=20.0, angle=90.0)
size = Size(width=1.0, height=0.5)
print(f"Position: {position}")
print(f"Size: {size}")
# Convert simple objects to S-expression
position_sexpr = position.to_sexpr_str()
print(f"Position S-expression: {position_sexpr}")
# Parse from S-expression
at_obj = At.from_sexpr("(at 10.0 20.0 90.0)", ParseStrictness.STRICT)
print(f"Parsed position: {at_obj}")
Error Handling Strategies
from kicadfiles import KicadPcb, ParseStrictness
import logging
# Configure logging to see warnings
logging.basicConfig(level=logging.WARNING)
# Test different strictness modes with a valid file
# STRICT mode - raises exceptions on errors
try:
pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.STRICT)
print("STRICT mode: File parsed successfully")
except ValueError as e:
print(f"Parsing failed: {e}")
# FAILSAFE mode - logs warnings, uses defaults for problems
pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.FAILSAFE)
print("FAILSAFE mode: File parsed with warnings logged for any issues")
# SILENT mode - uses defaults without warnings
pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.SILENT)
print("SILENT mode: File parsed silently, using defaults for any problems")
Advanced Usage Examples
Modifying PCB Files
from kicadfiles import KicadPcb, Footprint, At, ParseStrictness
# Load existing PCB
pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.STRICT)
# Example: Move all footprints by 5mm to the right
for footprint in pcb.footprints:
if footprint.at:
footprint.at.x += 5.0 # Move 5mm to the right
print(f"Moved footprint to ({footprint.at.x}, {footprint.at.y})")
# Save modified PCB (uncomment to actually save)
# pcb.save_to_file("output.kicad_pcb")
print("PCB modifications complete")
Working with Symbols
from kicadfiles import KicadSymbolLib, Symbol, Pin, At, ParseStrictness
# Load symbol library
lib = KicadSymbolLib.from_file("tests/fixtures/symbols/small.kicad_sym", ParseStrictness.STRICT)
# Examine all symbols in the library
for i, symbol in enumerate(lib.symbols):
pin_count = len(symbol.pins) if symbol.pins else 0
print(f"Symbol {i+1}: {pin_count} pins")
# List first few pins (to avoid too much output)
if symbol.pins:
for j, pin in enumerate(symbol.pins[:3]):
pin_name = pin.name.name if pin.name else "unnamed"
pin_number = pin.number.number if pin.number else "?"
print(f" Pin {pin_number}: {pin_name} at ({pin.at.x}, {pin.at.y})")
if len(symbol.pins) > 3:
print(f" ... and {len(symbol.pins) - 3} more pins")
# Create a new symbol
from kicadfiles import Number, PinName
from kicadfiles.enums import PinElectricalType, PinGraphicStyle
new_symbol = Symbol(
library_id="my_new_component",
pins=[
Pin(
at=At(x=0, y=2.54),
electrical_type=PinElectricalType.POWER_IN,
graphic_style=PinGraphicStyle.LINE,
length=2.54,
number=Number(number="1"),
name=PinName(name="VCC")
),
Pin(
at=At(x=0, y=-2.54),
electrical_type=PinElectricalType.POWER_IN,
graphic_style=PinGraphicStyle.LINE,
length=2.54,
number=Number(number="2"),
name=PinName(name="GND")
)
]
)
# Add to library and save (uncomment to actually save)
lib.symbols.append(new_symbol)
# lib.save_to_file("modified_library.kicad_sym")
print(f"Added new symbol, library now has {len(lib.symbols)} symbols")
Batch Processing
import os
from pathlib import Path
from kicadfiles import Footprint, ParseStrictness
# Process all footprints in the fixtures directory
footprint_dir = Path("tests/fixtures/footprints/")
for footprint_file in footprint_dir.glob("*.kicad_mod"):
try:
footprint = Footprint.from_file(str(footprint_file), ParseStrictness.STRICT)
# Analyze footprint
pad_count = len(footprint.pads) if footprint.pads else 0
print(f"{footprint_file.name}: {pad_count} pads")
# Example: Add metadata
if footprint.properties is None:
footprint.properties = []
# Save with modifications (uncomment to actually save)
# output_file = Path("processed") / footprint_file.name
# footprint.save_to_file(output_file)
print(f" Processed footprint with {pad_count} pads")
except Exception as e:
print(f"Error processing {footprint_file}: {e}")
Round-trip Verification
from kicadfiles import KicadPcb, ParseStrictness
# Load, convert to S-expression, and parse again
original_pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.STRICT)
# Convert to S-expression string
sexpr_string = original_pcb.to_sexpr_str()
# Parse the S-expression back to object
reconstructed_pcb = KicadPcb.from_sexpr(sexpr_string, ParseStrictness.STRICT)
# Verify complete equality
assert original_pcb.footprints == reconstructed_pcb.footprints
assert original_pcb.nets == reconstructed_pcb.nets
assert original_pcb.layers == reconstructed_pcb.layers
# test the complete object
assert original_pcb == reconstructed_pcb
print("Round-trip verification successful - objects are identical!")