Getting Started with moselpy
Topics covered in this chapter:
Introduction
moselpy combines Python's ecosystem with Mosel's optimization capabilities, leveraging Mosel's performance, portability, and security characteristics while enabling Python-based data preparation, result analysis, and workflow integration.
When to use moselpy
Use moselpy when you:
- have existing Mosel models and want to integrate them into Python applications
- prefer Mosel's algebraic modeling syntax, which closely mimics mathematical notation, for clarity and maintainability
- need pre-compiled models for performance optimization or intellectual property protection
- want to leverage Mosel's efficient integration with Xpress Solver while using Python for data preparation
- require seamless Pandas Series and DataFrames integration for input/output in data science workflows
- need iterative solving with Python-based logic between solves, combining Mosel's solving power with Python's flexibility
- are building data-driven optimization workflows that benefit from Mosel's efficiency and dynamic object support.
Prerequisites
moselpy requires:
- Python 3.11 to 3.15 (standard builds). Free-threaded Python 3.14t and 3.15t are supported as well.
- Optional: Pandas (for Series and DataFrame integration)
Installation
Install moselpy via PyPI:
pip install moselpy
This installs moselpy together with the Mosel runtime and the Xpress Solver libraries. If your models do not use the solver (that is, they do not load mmxprs or mmxnlp), you can install moselpy without the Xpress Solver libraries:
pip install moselpy-core
In both cases the Python module is imported as moselpy.
Verify installation:
import moselpy as mp
print(f"MoselPy version: {mp.version}")
print(f"Mosel version: {mp.mosel_version}")
print(f"Xpress version: {mp.xpress_version}") Runtime dependencies. moselpy is self-contained: the Mosel runtime is installed with it, and the Xpress Solver libraries are available through the xpresslibs package from PyPI, which pip install moselpy installs automatically.
Environment variables
The following environment variable is relevant when runningmoselpy :
- XPAUTH_PATH
- Path to the solver license file ( xpauth.xpr). Searched in standard locations if not specified. Only needed for solver-based models. The xpresslibs package includes a Community License; use this variable to point to a different license.
Your first model
We start with a simple Mosel model that prints a message. Create a file hello.mos:
model HelloWorld
writeln("Hello from Mosel!")
end-model Execute it from Python:
import moselpy as mp
# One-step: compile, load, and run
mp.execute_model("hello.mos") Output: Hello from Mosel!
The three-step workflow
For more control, use the three-step workflow: compile, load, run. The key functions are compile_model() to generate a compiled BIM file, load_model() to load it into memory, and run() to execute the model:
import moselpy as mp
# 1. Compile: .mos -> .bim
mp.compile_model("hello.mos", "hello.bim")
# 2. Load compiled model
model = mp.load_model("hello.bim")
# 3. Run
model.run()
print(f"Model '{model.name}' completed with status: {model.exec_status}") Output:
Hello from Mosel! Model 'HelloWorld' completed with status: ExecStatus.OK
The compiled .bim file is platform-independent and can be reused without recompilation, providing faster execution and intellectual property protection by hiding the model source code.
Model parameters
Pass parameters to Mosel models at execution time using the exec_params argument in the run() method. Parameters defined in the Mosel parameters block can be overridden from Python. Create greeting.mos:
model Greeting
parameters
NAME = "World"
end-parameters
writeln("Hello, ", NAME, "!")
end-model Run with different parameters:
import moselpy as mp
model = mp.load_model("greeting.bim")
# Method 1: Dict (recommended)
model.run(exec_params={"NAME": "Python"})
# Method 2: String
model.run(exec_params="NAME=MoselPy") Output:
Hello, Python! Hello, MoselPy!
The dict format handles special characters automatically and is the preferred option.
Stream redirection
Control where Mosel output goes using set_default_stream(). See Chapter Model Class for the full API reference of Model.set_default_stream().
Silencing output
Redirect output to the built-in null: driver to suppress it:
import moselpy as mp
model = mp.load_model("model.bim")
model.set_default_stream(mp.StreamType.OUTPUT, "null:")
model.set_default_stream(mp.StreamType.ERROR, "null:")
model.run() Capturing output
Redirect output to a Python buffer using the moselpy: driver. Register a StringIO object in the model's symbol registry, then route the stream through it. The buffer must be set before calling run():
import moselpy as mp
from io import StringIO
model = mp.load_model("model.bim")
buf = StringIO()
model.symbols["out"] = buf
model.set_default_stream(mp.StreamType.OUTPUT, "moselpy:out")
model.run()
del model.symbols["out"]
print(f"Captured: {buf.getvalue()}") Output: Captured: Hello from Mosel!
Global vs per-model redirection
Global stream settings affect all models that have not overridden their own streams. Per-model settings take precedence. Note that global settings via config.set_default_stream() must be set before the first load_model() call in the process. Once a model is loaded, only per-model set_default_stream() calls are possible:
import moselpy as mp
# Global: must be called BEFORE the first load_model()
mp.config.set_default_stream(mp.StreamType.OUTPUT, "null:")
# Per-model: can be called at any time, overrides global for this model only
model = mp.load_model("model.bim")
model.set_default_stream(mp.StreamType.OUTPUT, "output.txt") Pass None as the file name to restore the default stream (sys.stdout, sys.stderr, or sys.stdin).
Running a model from a string
For quick prototyping or generated models, you can define Mosel source directly as a Python string. Since compile_model() and execute_model() expect a file path, write the source to a temporary file, compile, run, then clean up:
import moselpy as mp
import tempfile, os
src = """model SumToN
declarations
n: integer
result: real
end-declarations
initializations from "moselpy:"
n
end-initializations
result := n * (n + 1) / 2.0
initializations to "moselpy:"
result
end-initializations
end-model"""
with tempfile.NamedTemporaryFile(mode="w", suffix=".mos", delete=False) as f:
f.write(src)
tmp_mos = f.name
tmp_bim = tmp_mos[:-4] + ".bim"
try:
mp.compile_model(tmp_mos, tmp_bim)
model = mp.load_model(tmp_bim)
output = model.run(input_data={"n": 100})
print(f"Sum 1..100 = {output['result']:.0f}")
finally:
for p in [tmp_mos, tmp_bim]:
if os.path.exists(p):
os.unlink(p) Output:
Sum 1..100 = 5050
This pattern is useful for testing small models interactively or for dynamically generating Mosel source from Python.
© 2001-2026 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.
