Pyomo reads its own version out of its own source at build time
An object-oriented algebraic modeling language in Python for structured optimization problems.
At a glance
- What is it?
- Pyomo is the object-oriented algebraic modeling layer in Python, and it ships no solvers of its own. Its packaging is the interesting part: the version, the dependency list and whether the compiled extension is built are all decided by setup.py while pyproject.toml declares those fields dynamic.
- Who is it for?
- Pyomo is the right layer when your optimization model has to be a Python object graph, because the examples and the problem-type list line up and because downstream packages such as mpi-sppy build parallel stochastic solvers on top of that property. Read three things before you commit.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- 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 6, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three files name the BSD terms while the repository licence field is empty
The licence is consistent in the source and absent in the metadata. The write-up says Pyomo is available under the BSD License and points at LICENSE.md, pyproject.toml declares `license = "BSD-3-Clause"` with `license-files = [ "LICENSE.md" ]`, and the header of setup.py repeats the 3-clause BSD terms together with a contract reference, Under the terms of Contract DE-NA0003525 with National Technology and Engineering Solutions of Sandia, LLC, adding that the U.S. Government retains certain rights in the software. The repository's own licence field, by contrast, carries no value at all, which is why the files are the only place to settle the question. The contribution terms match. Anyone sending a patch agrees the contribution is submitted under the BSD licence and represents that they are authorised to grant it, including on behalf of an employer with intellectual property rights over it. That clause is the one to read before contributing from inside a company, and it is why the copyright line runs to Sandia rather than to individual maintainers.
get_version execs a file inside the package to learn the version number
There is no version string in pyproject.toml because the file declares version, dependencies and optional-dependencies as dynamic, meaning setup.py generates all three. The version itself comes out of the package's own source, not out of git and not out of an environment variable. setup.py defines a helper that builds a path from the file's own directory, opens it, runs exec on its contents with `__name__` set to None, and hands back the resulting namespace:
def import_pyomo_module(*path):
_module_globals = dict(globals())
_module_globals['__name__'] = None
_source = os.path.join(os.path.dirname(__file__), *path)
with open(_source) as _FILE:
exec(_FILE.read(), _module_globals)
return _module_globalsThe caller asks that namespace for `__version__`:
def get_version():
return import_pyomo_module('pyomo', 'version', 'info.py')['__version__']So a packaging step executes a Python file from the package tree. The same file also reads setup arguments out of the PYOMO_SETUP_ARGS environment variable through check_config_arg, which strips recognised flags out of sys.argv as it goes.
Whether the compiled extension gets built depends on the command and the interpreter
Cython and pybind11 sit in the build requirements, but a comment in pyproject.toml says to leave Cython as an optional, runtime-selectable extra, because setuptools will still import it from setup.py when requested. The decision then lives in setup.py, where a constant named CYTHON_REQUIRED is set to required and the file inspects sys.argv to see whether the command being run is build, install, bdist or wheel. If none of those commands is present, using Cython is switched off outright. When one of them is present, the file also compares `sys.version_info[:2]` against (3, 11) and takes a different path for older interpreters, and the visible text stops inside that branch. The practical consequence is that the same source tree can produce different artefacts depending on which command you typed and which Python you typed it into. The metadata declares CPython 3.10 through 3.14 and PyPy 3.11, and requires-python is set at 3.10 or newer, so the older-interpreter branch is a supported configuration rather than a legacy leftover.
The problem-type list and the examples tree are the same list twice
The scope statement is a list of eleven problem types, and the repository layout repeats it directory by directory. Linear, quadratic, nonlinear, mixed-integer linear, mixed-integer quadratic and mixed-integer nonlinear programming come first, then mixed-integer stochastic programming, generalized disjunctive programming, differential algebraic equations, mathematical programming with equilibrium constraints, and constraint programming. Under examples/ the same families appear as dae/, gdp/, mpec/, pyomo/, pyomobook/, doc/, kernel/ and performance/. That is a useful cross-check for anyone evaluating fit: if your problem has no matching subdirectory, the claim is thin. The other half of the scope is that Pyomo formulates rather than solves. It defines symbolic problems, creates concrete problem instances, and hands those instances to standard solvers, which is why the write-up never names a solver interface. Downstream packages fill that gap, and mpi-sppy is given as the example, using the fact that Pyomo's modeling objects sit inside a full-featured high-level programming language to parallelise subproblems transparently through Python parallel communication libraries.
Two continuous integration systems guard the same default branch
The badges at the top of the write-up point at a GitHub Actions workflow named test_pr_and_main.yml, filtered to the main branch on push events, and at a Jenkins instance hosted on Sandia's own domain, with a third badge for coverage. The repository carries both surfaces: a .github/ directory and a .jenkins.sh script at the root, alongside .codecov.yml, .coveragerc and conftest.py. Testing runs on CPython 3.10, 3.11, 3.12, 3.13 and 3.14, plus PyPy 3.11, and the classifiers in pyproject.toml list the same set. The support policy is stated as a rule rather than a date: at the time of the first Pyomo release after the end-of-life of a minor Python version, testing for that version is removed. That is a self-executing policy tied to the release calendar, so the interpreter list in the write-up is a moving target rather than a fixed promise. Anyone pinning an old Python in production is reading a document that the project has committed to shrinking.
The write-up carries a marker that the release process deletes everything above
One line in the write-up explains its own layout. A comment reads, the Pyomo release process will REMOVE-EVERYTHING-BEFORE-THIS-LINE, and everything above it is badges: the Actions workflow link, the Jenkins link, the codecov link, the readthedocs link, a contributors graph and a merged pull requests query. The COIN-OR link sits immediately below the marker. So the first thing the release script does is wipe that block and rebuild it, which means the badge text is machine-managed and its wording is not a human promise. It is also a small warning about the file as a source: the part you read first is the part nobody edits by hand. Everything below the marker is prose, and the prose covers what Pyomo is, what it is not, how to install it, and where to ask questions. The first Pyomo release after a Python version reaches end-of-life is the other automated edit, and both of them happen without a commit message that describes intent.
The name changed once and the repository moved in 2016
Pyomo was formerly released as the Coopr software library, which explains older documentation, old Stack Overflow answers and downstream requirements still naming coopr. The other dated fact is where the code lives: development moved to this repository in June 2016 from Sandia National Laboratories, and developer discussions are hosted on Google Groups. Coordination is weekly, on Tuesdays from 12:30 to 14:00 Mountain Time, with call-in information requested by email to [email protected], a pattern that still reflects a team organised around one US laboratory. Help for users goes elsewhere, through the pyomo tag on StackOverflow and a Pyomo forum on Google Groups, and the tutorial trail points at a Springer book on optimization modeling in Python, a workshop slide deck dated December 2023, a third-party cookbook, companion notebooks for a hands-on book, and a separate gallery repository. Note the spread of dates there: a 2023 deck next to releases dated 2026.
The newest release is four months behind the last push
The tag history is a plain list with long gaps. 6.9.5 was published on 2025-10-17, 6.10.0 on 2026-02-20, and 6.10.1 on 2026-06-04. That is roughly four months between the first two and three and a half between the next, with a minor version bump at 6.10.0 rather than a patch-level bump. The last push on the default branch is dated 2026-09-30, about four months after 6.10.1 and with no newer tag attached, and the tree carries both a CHANGELOG.md and a RELEASE.md at the root for anyone who needs the detail the tags do not carry. Two installation channels are offered and they are not identical in content: `pip install pyomo` from PyPI, and `conda install -c conda-forge pyomo` from conda-forge. Nothing in the write-up says when the two channels are in sync, so an environment that mixes them can end up with two versions of the same package, and 3.10 is the floor for either.
Editorial conclusion
Pyomo is the right layer when your optimization model has to be a Python object graph, because the examples and the problem-type list line up and because downstream packages such as mpi-sppy build parallel stochastic solvers on top of that property. Read three things before you commit. First, the licence: the write-up, pyproject.toml and the setup.py header all say the 3-clause BSD terms, with a U.S. Government retention clause from the Sandia contract, while the repository's own licence field carries no value at all. Second, the build: the version, the dependency list and the Cython decision come out of setup.py, so building from a source checkout and building from a wheel are not the same exercise. Third, the solver question the project never answers, because Pyomo formulates models and leaves solving to whatever standard solver you attach.
Frequently asked questions
Is Pyomo free?
The write-up states Pyomo is available under the BSD License, and pyproject.toml declares BSD-3-Clause with LICENSE.md as the licence file. The setup.py header repeats the 3-clause BSD terms and notes that the U.S. Government retains certain rights under contract DE-NA0003525.
What does Pyomo stand for?
The file header in setup.py reads Pyomo: Python Optimization Modeling Objects. The write-up itself does not expand the name, and it also records that Pyomo was formerly released as the Coopr software library.
how to install pyomo
From PyPI with `pip install pyomo`, or from conda-forge with `conda install -c conda-forge pyomo`. Requires-python is set at 3.10 or newer, and the tested interpreters are CPython 3.10 through 3.14 plus PyPy 3.11.
how to install pyomo in anaconda
The Anaconda path is the conda-forge channel: `conda install -c conda-forge pyomo`. The write-up lists it as a separate channel from the PyPI one and does not describe how the two are versioned against each other.
how to use gurobi with pyomo
That wiring is not described here. The write-up says Pyomo creates concrete problem instances and solves them with standard solvers, and points to pyomo.readthedocs.org for the rest. The repository ships no Gurobi-specific code in the examples tree.
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/pyomo-pyomo)