Constructing and solving any Gurobi model requires creating a Gurobi environment. While in other APIs Gurobi environments must be explicitly created and destroyed, gurobipy includes the default environment. The default environment simplifies matters when you are actively experimenting with model formulation in an interactive environment (e.g. a Python shell, IPython, or a Jupyter notebook).
Many of our example codes (e.g. mip1.py) use a pattern that uses the default environment and does not explicitly dispose of it at the end of the code. These examples are intended only to illustrate the basic usage of key features of gurobipy. In production systems you should be more careful: we strongly recommend explicitly managing environments to prevent resource leaks. This is particularly important when remote resources are involved or if there are usage limits on your license, i.e.
- Compute server: a job slot is occupied until the environment is closed.
- Floating use (token server) license: your process occupies a license token until the environment is closed.
- WLS license: your process occupies a license token until the environment is closed and the token lifespan has expired.
- Single-use license: no other processes on the machine can use Gurobi until you close the environment.
- Gurobi Instant Cloud: a machine is kept active with a job slot occupied until the environment is closed.
The correct way to manage environments in gurobipy is to use context managers, just as you should whenever opening a file or connection in any other Python library. Below are two possible patterns; the example mip1_remote.py provides a more complete code.
- To solve a single model tied to a single environment:
import gurobipy as gp
with gp.Env() as env, gp.Model(env=env) as model:
# construct, solve, and post-process `model`
x = model.addVar()
...
model.optimize()
...
# At the end of the block, the environment is explicitly freed,
# even if there is an error. This returns resources to the compute
# server or instant cloud, or releases limited use licenses so
# that tokens are not held for too long.- When solving many models sequentially, it may be better to use a single Gurobi environment to avoid paying the overhead cost multiple times. To use multiple models in sequence within an environment:
import gurobipy as gp
with gp.Env() as env:
with gp.Model(env=env) as model1:
# formulate and solve model1
with gp.Model(env=env) as model2:
# formulate and solve model2
# The two models share one license or connection, which is closed
# at the end of the environment block.Note that if you do not manage environments explicitly, then by default the environment lives as long as your process. In this case, your WLS token, floating license token, Compute Server connection, or Instant Cloud machine will stay active until your process dies.
A pattern for use with object oriented programming
Many users like to design their Gurobi application using object oriented programming. A consequence is that the Gurobi environment and model are often created within a class, like so:
import gurobipy as gp
class MyOptimizer:
def __init__(self):
self.env = gp.Env()
self.model = gp.Model(env=env)
...An alternative pattern we recommend is to pass the environment and model to the class. This will make your design more flexible, reducing the responsibilities for your class and decoupling the environment handling from the model building. This will make testing and debugging easier but the main advantage is making the use of context managers easier:
import gurobipy as gp
class MyOptimizer:
def __init__(self, model):
self.model = model
...
with gp.Env() as env, gp.Model(env=env) as model:
my_optimizer = MyOptimizer(
model=model,
...
)
...Adopting this pattern can mitigate many (often cryptic) errors that often arise due to weaknesses in environment handling.