Using KiCad’s Python (“kipython”) for headless pcbnew¶
pcbnew.py from KiCad v7+ does not import reliably when running Python from a Terminal (outside the KiCad GUI). Everything works fine when inside the GUI, but not outside in this “headless” mode.
The workaround is to use KiCad’s bundled python3 executable and give it a short name on your PATH. We will call it kipython.
When do I need this?¶
If you want to use pcbnew.py for scripting independent of a GUI Application and you are using MacOS or Windows, you will need this workaround step. Linux does not need it.
Quick start¶
Run the setup:
python -m kigadgets
Verify
kipythonworks:kipython -c "import pcbnew; print('pcbnew import OK')"
If you need third-party packages for your script, install them for
kipython:kipython -m pip install --user numpy
Detailed Setup¶
macOS: symlink (one time)¶
Run the usual setup script python -m kigadgets. It will detect if you need this workaround and guide you through it.
On macOS, it is effectively running this command:
ln -s "/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3" /usr/local/bin/kipython
plus checks to make sure those places exist and are writable. It will prompt you before making the symlink in case you want to replace /usr/local/bin with somewhere else on your PATH. Check that kipython symlink is working like this
$ which kipython
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3
Windows: PowerShell function / alias¶
Run the usual setup script python -m kigadgets. It will detect if you need this workaround and guide you through it.
On Windows, automatic symlinking is disabled. The python -m kigadgets setup will print a PowerShell alias command for you that looks like:
function kipython { & 'C:\\Program Files\\KiCad\\8.0\\bin\\python.exe' @args }
It is up to you how to make this alias persistent. Put it in your PowerShell profile (see $PROFILE). Or, if you use a different shell, create the equivalent alias/function for that shell.
Verify¶
Basic import test. Run this in any terminal:
$ kipython -c "import pcbnew; print('pcbnew import OK')"
For more verification about the interpreter:
$ kipython --version
$ kipython -c "import sys; print('Executable:', sys.executable)"
$ kipython -m kigadgets
Using third-party packages with kipython¶
kipython is within KiCad.app, so modifications made will be installed Application-wide. It is the same python used in the GUI by action plugins. kipython does not see your venv or conda environment packages active in a given Terminal. It does see your shell environment variables, including $PYTHONPATH.
Caution |
|---|
Installing things with |
Suppose we have a script or module that combines headless pcbnew and some heavier packages
# myscript.py
import kigadgets, pcbnew, numpy, tensorflow
def do_some_pcb_AI():
...
Typically, we get dependencies and launch that like this:
$ python -m pip install numpy tensorflow
$ python myscript.py
On Linux: this works as expected out of the box in any terminal with any compatible python interpreter.
On macOS and Windows: you need to use bundled kipython for both execution and installation, and you need to install in such a way to not pollute the KiCAD environment unintentionally.
Don’t do this¶
$ kipython -m pip install numpy tensorflow
$ kipython myscript.py
This will ususally run; however, kipython -m pip will install packages directly into the KiCad application bundle. The change is seen Application-wide, and this can cause code signature issues on macOS. You can break the entire KiCAD application this way.
Recommended: install with --user¶
The simple solution is with --user flag with KiCAD-bundled pip
$ kipython -m pip install --user numpy tensorflow
$ kipython myscript.py
That’s it. It won’t corrupt your system or your KiCad installation.
I know: many install instructions include --user for the sake of good practice. Here, it is actually very important to use the --user flag. It will install somewhere safe like “~/Library/…/site-packages”, rather than somewhere inside the KiCad application bundle.
If you forget --user and then try to install binaries and MacOS invalidates the application’s code signature, read KiKit’s explanation of KiCad code signatures. Otherwise, reinstall the app to restore the code signature.
Advanced: explicit installation paths¶
Using bundled pip with an external package location
This is doing the same thing as --user except putting it in a custom location. It is useful if you want to create multiple encapsulated pseudo-environments
$ mkdir -p ~/Documents/KiCad/python3rdparty/site-packages
$ kipython -m pip install --target ~/Documents/KiCad/python3rdparty/site-packages numpy tensorflow
Then make sure that is on the sys.path that kipython will search for imports.
Option 1: call your entry point like this. It does see your shell environment variables, including $PYTHONPATH.
$ export PYTHONPATH="~/Documents/KiCad/python3rdparty/site-packages:$PYTHONPATH"
$ kipython my_script.py
Option 2: write your entry point like this.
# myscript.py - edited
import sys
sys.path.insert(0, '~/Documents/KiCad/python3rdparty/site-packages')
import kigadgets, pcbnew, numpy, tensorflow
Advanced: external package managers¶
$ kipython --version
Python 3.9.13
$ mamba create -n pcbtf python=3.9.13
$ mamba activate pcbtf
(pcbtf) $ pip install tensorflow
(pcbtf) $ pip show tensorflow
...
Location: /Users/username/micromamba/envs/pcbtf/lib/python3.9/site-packages
...
$
and then put that Location on sys.path using a method above.
$ export PYTHONPATH="/Users/username/micromamba/envs/pcbtf/lib/python3.9/site-packages:$PYTHONPATH"
$ kipython my_script.py
This is not guaranteed to work because there are two pips trying to coordinate, yet it almost always does when using the same python version on the same machine.
To skip typing that export line, you can add it as an environment activation hook at: ~/micromamba/envs/pcbtf/etc/conda/activate.d/explicit_pythonpath.sh. Run then looks like
$ mamba activate pcbtf
(pcbtf) $ kipython my_script.py