I my previous post, I talked about querying for information about your layout. In this one I’ll show you how to create your own wires/vias from python. I also cover moving modules. Most of the code is self-explanatory but I find it helpful to have sample “cookbook” code.
The main thing to keep in mind when creating new objects is that even though you have to pass a board pointer to the constructors, you still have to call board.Add(obj). Also, you have to add it before setting the net. If you try to set the net before, it’ll do nothing.
Remember that the units are 1E-6mm. So if you have a mm value multiply it by a million.


First, let’s generate our layer mapping

layertable = {}
numlayers = pcbnew.LAYER_ID_COUNT
for i in range(numlayers):
 layertable[i] = board.GetLayerName(i)
 print("{} {}".format(i, board.GetLayerName(i)))

Add a track

track = pcbnew.TRACK(board)
track.SetStart(pcbnew.wxPoint(136144000, 95504000))
track.SetEnd(pcbnew.wxPoint(176144000, 95504000))

Add a via

In this case, I’m going to copy an existing via. Note that there is also the clone method, but doing it this way you’ll know how to generate a via from scratch.
There isn’t yet a direct way to query a via for its layers. The way I work around this is by looping through all layers and calling IsOnLayer This is one of the reasons I’m showing how to copy an existing via.
The via types will be one of these:

  • pcbnew.VIA_THROUGH
  • pcbnew.VIA_MICROVIA

The width if the via is the diameter. If you forget to set this, you’ll get funny behavior where via disappears from the display when you zoom in.

newvia = pcbnew.VIA(board)
# need to add before SetNet will work,
# so just doing it first
for l in range(pcbnew.LAYER_ID_COUNT):
   if not track.IsOnLayer(l):
   toplayer = max(toplayer, l)
   bottomlayer = min(bottomlayer, l)
# now that I have the top and bottom layers, I tell the new
# via
newvia.SetLayerPair(toplayer, bottomlayer)

Moving a module

I haven’t tried creating a new module yet. I prefer to let the netlist importer do this for me. I do, however, find it useful to be able to move modules. They all come in on top of each other. There are a variety of placement algorithms one might want to implement. 1
Note that the orientation is degrees*10.0

peer.SetPosition(pcbnew.wxPoint(newx, newy))

Class diagram

I’ve created a class diagram to help me remember. Click to enlarge. Also available in my github

modifying pcbnew layout from python

  1. In my previous professional life, one of the more interesting ones I saw was using linear programming. You start with everything in the middle. You create a set of equations representing net connectivity as well as cell overlaps. Solve the equations. Repeat. It was good for a couple hundred thousand cells. Much more than what PCB requires. Simulated Annealing would likely be easier here.

4 thoughts on “modifying pcbnew layout from python

  • May 12, 2017 at 5:45 pm

    This is really valuable information – the best I’ve found so far. Thank you!
    I’ve managed to create filled zones, but I’m stumped on how to add text to the silkscreen layer.
    Any clues?

  • April 10, 2018 at 8:48 pm

    I tried to make a via by following your article, only using pcbnew.F_Cu and pcbnew.B_Cu instead of the layer search thing you do. I have the problem that my via is there, hidden, when I select it it shows, but when I click somewhere else it disappears again. Seems like something is missing to make it render when not selected?
    You got any idea?

    • September 7, 2018 at 8:14 am

      Sorry it’s taken me so long to reply.
      There are two solutions to this.
      1) if you run your code in pcbnew’s plugin feature, the refresh (and undo) is taken care of for you.
      2) from the scripting console, you can do pcbnew.Refresh().

  • May 5, 2019 at 7:29 pm

    `pcbnew.LAYER_ID_COUNT` seems to be gone in 5.1.2.
    Any other ideas how to get layers so that a layer can be assigned to a new track?


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.