PySpice: driving Ngspice and Xyce from Python objects
Simulate electronic circuit using Python and the Ngspice / Xyce simulators
At a glance
- What is it?
- PySpice wraps the Ngspice and Xyce circuit simulators behind an object oriented Python API, so a circuit can be built, simulated and plotted from a script instead of a netlist file. The tradeoff is that it binds to external simulator binaries, carries a GPLv3 licence, and is maintained by one developer in spare time.
- Who is it for?
- PySpice fits an engineer who already knows SPICE, wants circuits defined in Python rather than in a netlist, and needs results as Numpy arrays that can be swept and plotted. It does not fit a team that needs a vendor-supported simulator, a permissive licence for closed-source products, or a maintained support channel, since the author states the project is developed in his free time and the Discourse forum was closed for lack of activity.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 50 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What PySpice actually wraps
PySpice is a Python module that interfaces Python to the Ngspice and Xyce circuit simulators. The repository README lists the feature set plainly: support for both simulators, support for Linux, Windows and Mac OS X, an Ngspice shared library binding implemented with CFFI that supports external sources, a partial SPICE netlist parser, an oriented object API to define a circuit, simulation output exported to Numpy arrays, plotting with Matplotlib, unit handling, work with the KiCad schematic editor, a documentation generator, and many examples.
Two of those entries set the character of the project. The CFFI binding means PySpice is not a text generator that writes a netlist and shells out; for Ngspice it can load the shared library directly and drive the simulator in process, with external sources handled through that binding. The partial netlist parser, by contrast, is explicitly incomplete, which tells you where the intended workflow sits: the Python API is the primary path and netlist import is a convenience, not the core.
The repository layout supports that reading. There are example directories for analyses, basic usages, operational amplifiers, filters, transformers, relay logic, switched power supplies, spice-parser work and ngspice-shared usage, plus separate c-examples and data-analysis folders. There is also a unit-test directory and a unit-test-todo directory, a tox.ini and a Travis CI configuration, which tells you testing exists but that some tests are still parked as work to do.
The Python version floor and the dependency set
The packaging is old-fashioned in a way that tells you the era of the code. setup.py begins with an explicit guard that checks the interpreter before anything else runs:
required_python_version = (3, 6)
if sys.version_info < required_python_version:
sys.stderr.write('ERROR: PySpice requires Python {}.{}\n'.format(*required_python_version))
sys.exit(1)The runtime dependencies are listed in requirements.txt as a small, dated set:
PyYAML>=5.3
cffi>=1.14
matplotlib>=3.2
numpy>=1.18
ply>=3.11
scipy>=1.4Reading that list explains the design. ply is a Python implementation of lex and yacc, which is how the SPICE netlist parser is built. cffi is the bridge to the Ngspice shared library. numpy, scipy and matplotlib carry the numeric output and plotting work. PyYAML is what the documentation generator reads for its source files. None of these are heavy or exotic, but the floor on scipy and numpy is high enough that an old locked environment will not work without an upgrade.
The setup.py also carries an unresolved comment, `Fixme: could check for ngspice, Xyce, libngspice.so etc.`, next to commented-out code that would have run `ngspice --version` and printed a warning when the binary was missing. In other words, the check was considered and not implemented. PySpice will not tell you at install time that your simulator is absent; you find out at simulation time.
Getting a simulator in place before the first circuit
The README does not give a one-line install for the simulators themselves; it points at the installation section of the documentation site, and it lists the conda-forge channels for both PySpice and ngspice so that a conda-based environment can supply the binary alongside the package. What the repository does show is the dependency list, which is the part you control.
Whether you use the shared library binding or a subprocess invocation of the ngspice binary depends on the simulator build you have. The examples directory separates `ngspice-shared` from `c-examples`, which reflects the two paths through the code. The README also records a specific gotcha for the shared library path: an issue was found with Ngspice Shared, and the note says you must `setlocale(LC_NUMERIC, "C");`, linking the ngspice bug tracker entry 490. A locale that formats numbers with commas instead of periods will break a simulator that expects C style numeric parsing, and that call is not optional in the shared configuration.
One more dependency detail is worth planning for. The pyproject-era summary of the project's requirements does not list a simulator at all, and the repository includes its own `ngspice-feedstock` and `pyspice-feedstock` directories, conda recipes maintained inside the repository. That is a hint about who does the work: you are relying on one maintainer for both the Python package and the packaging recipe for the binary it drives.
Where the parser is incomplete and where the KiCad path leads
The netlist parser is described in the README as partial, and the 2024 update note lists a fix for the Spice parser among the changes on the development branch. A partial parser is not a bug so much as a boundary, and it sets the dividing line between the two ways people use PySpice. If your circuits already exist as netlists from another tool, you are in the part of the project with known gaps. If you define the circuit in Python, you are on the path the library was built around.
The KiCad direction is the most interesting feature in the release notes. The development release includes KiCadTools, described as a proof of concept module that reads the KiCad 6 `.kicad_sch` schematic file and computes the netlist. The README is explicit about the intent: the module can be used to perform any kind of processing on a KiCad schematic, and it is actually hosted in the source but could become a standalone project. For PySpice it offers a way to draft a circuit in KiCad and then generate the netlist without using the netlist export feature of KiCad itself.
That framing matters for an evaluation. A proof of concept means you should expect the schema handling to be narrow. It reads one specific KiCad file format, the KiCad 6 schematic schema. If your schematics live in a newer KiCad release, or if you rely on KiCad's own netlist export with its symbol and footprint libraries, this module buys you nothing and adds a second dependency on a format you do not control.
Release cadence, versions and the licence question
The repository has no GitHub releases at all, so version history has to be read from the README news section. V1.5.0 is the production release, dated 2021-05-15, and it brought support for Ngspice up to version 34 among other changes. V1.6.0 is listed as a development release and is where KiCadTools appears. The last push to the repository was on 2026-09-03, so work continues, but the absence of tagged releases means there is no packaged version to pin to unless you build from source or take whatever conda-forge publishes.
The 2024 update section carries a disclaimer that is worth reading before you plan around this dependency: PySpice is developed on the author's free time, so he could be busy with other tasks and be less reactive. The same section states that the free Discourse forum was closed some time ago due to a lack of activity, and that a HTML backup is stored in the `pyspice-discourse-backup` directory. The project does have a Discourse forum at pyspice.discourse.group, but the historical caveat tells you what kind of support channel to expect.
The licence is GPLv3, and the repository ships GPL-V3.0.txt and LICENSE.txt. For a design or research workflow that is a non-issue. For a company shipping closed-source tooling that links against PySpice, the copyleft terms of a library you import and call are a question for your own legal team, and PySpice's own site is not the place to get that answered.
Where PySpice is the wrong tool
There are clear cases where another route is better. If you want a simulator you can trust for sign-off on a physical board, with a vendor behind it and documented tolerance models, PySpice adds a translation layer between you and the tool rather than removing one. The README itself describes the SPICE netlist parser as partial and the KiCad integration as a proof of concept, and those two statements describe the edges of the usable area.
If your work is already a netlist file and you need the simulator's full feature set, writing the netlist directly and calling the ngspice binary is fewer moving parts. PySpice earns its place when you want to parameterise a circuit in Python, sweep values programmatically, keep results in Numpy arrays for analysis, and plot them, or when you want the circuit definition to live in version control next to the code that post-processes it. That is the workflow the object oriented API exists for.
The maintenance dimension is the practical limit. A library that binds to an external C simulator through CFFI carries the churn of both sides. The 2024 notes mention fixing the Ngspice library loading for recent cffi and fixing a simulation abort caused by a message from newer ngspice. Those are exactly the failures you hit when the simulator releases a new version, and they were addressed on the development branch rather than in a tagged production release.
Editorial conclusion
PySpice fits an engineer who already knows SPICE, wants circuits defined in Python rather than in a netlist, and needs results as Numpy arrays that can be swept and plotted. It does not fit a team that needs a vendor-supported simulator, a permissive licence for closed-source products, or a maintained support channel, since the author states the project is developed in his free time and the Discourse forum was closed for lack of activity. Before adopting it, confirm that the ngspice or Xyce binary you plan to use is on the path, that the versions supported by the release you install include your simulator, and that GPLv3 obligations fit your distribution model.
Frequently asked questions
What does PySpice do and which simulators does it support?
PySpice is a Python module that interfaces Python to the Ngspice and Xyce circuit simulators, letting you define a circuit with an oriented object API, run the simulation and export the output to Numpy arrays.
How do I install PySpice and its dependencies?
The README points to the installation section of the PySpice documentation site and lists the conda-forge channels for both PySpice and ngspice. The Python dependencies are listed in requirements.txt as PyYAML>=5.3, cffi>=1.14, matplotlib>=3.2, numpy>=1.18, ply>=3.11 and scipy>=1.4.
Do I need ngspice or Xyce installed separately to use PySpice?
Yes. PySpice drives the external simulators, and the setup.py in the repository carries an unimplemented check for ngspice, Xyce and libngspice.so, so a missing simulator is not reported at install time. The README also notes that the Ngspice shared library path requires setlocale(LC_NUMERIC, "C") because of an ngspice bug.
Can PySpice read a netlist or a KiCad schematic?
The README describes a partial SPICE netlist parser, and the development release adds KiCadTools, a proof of concept module that reads the KiCad 6 .kicad_sch schema and computes the netlist without using the KiCad netlist export feature.
How often is PySpice released and what licence does it use?
The repository has no GitHub releases, and the README news section lists V1.5.0 as the production release from 2021-05-15 with V1.6.0 as a development release. The project is licensed under GPLv3, and the last push to the repository was on 2026-09-03.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pyspice-org-pyspice)Was this useful?