手动安装Gurobi并配置gurobipy到Python环境(Windows/Conda)

1. 问题背景

Gurobi商用时需要gurobipy与本地Gurobi安装包版本匹配,并且正确读取许可证文件。很多同学卡在"安装包已经有了,pip也装了,import就是报错"这一步。

本文记录完整的排查和配置流程,环境:Windows 11 + Anaconda Python 3.12 + Gurobi 13.0

2. 确认Gurobi安装包状态

Gurobi的Windows安装包默认路径在 C:\gurobi<版本号>\win64\

# PowerShell 或 Git Bash 下执行
ls C:\gurobi1300\win64\bin\

# 关键文件检查清单:
# ✅ gurobi_cl.exe       — 命令行求解器
# ✅ gurobi.lic           — 许可证文件
# ✅ grbgetkey.exe        — 许可证获取工具
# ✅ gurobi130.dll        — 动态链接库(后续Python调用依赖)

许可证文件gurobi.lic)内容长这样:

TYPE=NODE
VERSION=13
HOSTNAME=你的机器名
HOSTID=你的MAC地址
EXPIRATION=2027-11-29
KEY=XXXXXX

如果你是学术用户,从学校或Gurobi官网申请license后,用grbgetkey.exe下载。如果是企业用户,直接拿到gurobi.lic放到bin/下即可。

3. Python环境匹配是核心坑

3.1 先搞清楚你用哪个Python

# 查看当前Python路径和版本
python --version          # 例如 Python 3.12.7
python -c "import sys; print(sys.executable)"
# 输出: D:\anaconda3\python.exe

gurobipy的wheel包是与 Python主版本号严格绑定的:

  • cp311 → Python 3.11
  • cp312 → Python 3.12

如果你用错pip(比如系统Python装到了Conda Python的环境里),会报ModuleNotFoundError: No module named 'gurobipy'

3.2 用正确的pip安装

# 关键:用 python -m pip,确保pip和Python是同一个环境
python -m pip install gurobipy

pip会自动根据当前Python版本拉取匹配的wheel:

Downloading .../gurobipy-13.0.1-cp312-cp312-win_amd64.whl (11.2 MB)
    ↑                ↑
    版本号           cp312 = Python 3.12, win_amd64 = Windows 64位

3.3 常见报错与排查

报错原因解决
ModuleNotFoundError: No module named 'gurobipy'pip装到了另一个Python环境python -m pip install gurobipy
ImportError: DLL load failedgurobi130.dll不在PATH中C:\gurobi1300\win64\bin加到系统PATH
No Gurobi license found许可证文件找不到检查gurobi.lic是否在bin/下,或设环境变量GRB_LICENSE_FILE

4. 验证安装

写一个完整的测试脚本,一次性验证:导入 → 许可证 → 建模 → 求解 → 获取结果。

import gurobipy as gp

def test_gurobi():
    """最小模型验证Gurobi全链路是否正常。"""
    print("gurobipy version:", gp.__version__)

    # 创建模型
    m = gp.Model("test")

    # 添加变量:x是binary决策变量,y是连续变量
    x = m.addVar(vtype=gp.GRB.BINARY, name="x")
    y = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="y")

    # 添加约束:x + y <= 10
    m.addConstr(x + y <= 10, "c0")

    # 设置目标:最大化 y
    m.setObjective(y, gp.GRB.MAXIMIZE)

    # 求解(OutputFlag=1显示日志,=0静默)
    m.setParam("OutputFlag", 1)
    m.optimize()

    # 检查结果
    if m.Status == gp.GRB.OPTIMAL:
        print(f"Status: OPTIMAL")
        print(f"x = {x.X}")      # 预期 0.0
        print(f"y = {y.X}")      # 预期 10.0
        print(f"Obj = {m.ObjVal}")  # 预期 10.0
        return True
    else:
        print(f"FAILED. Status: {m.Status}")
        return False

if __name__ == "__main__":
    success = test_gurobi()
    print("\n✅ 环境正常" if success else "\n❌ 环境异常,排查上述报错")

预期输出(截取关键行):

gurobipy version: 13.0.1
Restricted license - for non-production use only - expires 2027-11-29
Gurobi Optimizer version 13.0.1 build v13.0.1rc0 (win64 - Windows 11+.0)

Thread count: 14 physical cores, 20 logical processors, using up to 20 threads

Optimal solution found (tolerance 1.00e-04)
x = 0.0
y = 10.0
Obj = 10.0

✅ 环境正常

如果能跑到这一步,说明 Python绑定、DLL链接、许可证校验、求解器内核 全部正常。

5. 环境变量配置(可选但推荐)

如果不想每次打开终端都检查DLL路径,建议把Gurobi路径加入系统环境变量。

# 管理员PowerShell下执行
[Environment]::SetEnvironmentVariable(
    "GRB_LICENSE_FILE",
    "C:\gurobi1300\win64\bin\gurobi.lic",
    "User"
)

或在 系统属性 → 环境变量 → Path 中添加:C:\gurobi1300\win64\bin


6. 许可证文件管理与替换

许可证是 Gurobi 使用中更换频率最高的部分——学术许可证每年续期、换电脑后 HOSTID 变化、商业许可证升级等场景都需要替换。本节覆盖完整的替换流程。

6.1 什么时候需要替换许可证

场景现象需要做什么
许可证过期报错 License expired续期并下载新 .lic
换了电脑/重装系统报错 Host ID mismatch重新申请绑定新机器的 .lic
MAC 地址变更同上(HOSTID 绑定 MAC)同上
升级 Gurobi 大版本报错 License version mismatch申请匹配新版本的 .lic
从 WLS 切换到本地许可证规模受限(变量数上限 2000)获取本地 .lic 文件

6.2 学术许可证申请(免费)

Gurobi 对学术用户提供免费许可证,但需要 .edu 邮箱注册。

步骤 1:注册 Gurobi 账号

访问 https://www.gurobi.com/academia/academic-program-and-registrations/ ,用学校邮箱注册。

步骤 2:生成许可证密钥

登录后进入 https://portal.gurobi.com/iam/licenses/ ,点击 “Generate License”

选择许可证类型:

  • Named-User Academic — 绑定单台机器(最常用)
  • Floating Academic — 浮动许可证(需学校服务器,一般不需要)

点击后会得到一个形如 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 的密钥。

步骤 3:下载许可证文件

方法 A:用 grbgetkey(推荐)

# 在 PowerShell 中执行,替换为你的密钥
C:\gurobi1300\win64\bin\grbgetkey.exe xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

执行过程:

info : grbgetkey version 13.0.1
info : Contacting Gurobi license server...
info : License 1234567 for user yourname@university.edu
info : License type: NAMED-COMPUTER
info : Host ID detected: aabbccddeeff

Where should we store the license file?
Press enter to accept the default path (C:\gurobi1300\win64\bin\gurobi.lic)
>

按 Enter 即可,默认存到 bin\ 下。

方法 B:手动下载

在 Gurobi Portal 页面直接点击 “Download License File”,下载 gurobi.lic 文件,然后手动复制到 C:\gurobi1300\win64\bin\

6.3 替换许可证文件(核心操作)

替换本质上就是覆盖旧的 gurobi.lic 文件

# Step 1: 备份旧许可证(可选但推荐)
copy C:\gurobi1300\win64\bin\gurobi.lic C:\gurobi1300\win64\bin\gurobi.lic.bak

# Step 2: 用 grbgetkey 下载新许可证(会自动覆盖)
C:\gurobi1300\win64\bin\grbgetkey.exe 你的新密钥

# 或者:手动复制下载的 gurobi.lic 到 bin 目录
copy Downloads\gurobi.lic C:\gurobi1300\win64\bin\gurobi.lic

Step 3: 验证新许可证

# 用命令行工具检查
C:\gurobi1300\win64\bin\gurobi_cl.exe --license

预期输出:

Gurobi license valid
License type    : NAMED-COMPUTER
Expiration date : 2027-11-29
...

再用 Python 验证:

import gurobipy as gp
m = gp.Model("test")
m.setParam("OutputFlag", 0)
x = m.addVar()
m.setObjective(x)
m.optimize()
print(f"License OK, Gurobi {gp.gurobi.version()}")

6.4 许可证文件存放位置优先级

Gurobi 按以下顺序查找许可证文件:

优先级查找位置说明
1环境变量 GRB_LICENSE_FILE 指定的路径绝对路径,最高优先
2%HOME%\gurobi.lic用户主目录下
3C:\gurobi<ver>\win64\bin\gurobi.lic安装目录下(默认)
4%GRB_LICENSE_FILE% 目录下的 gurobi.lic如果环境变量指向目录而非文件

常见坑:如果 GRB_LICENSE_FILE 环境变量指向旧路径,即使你替换了 bin\ 下的 .lic,Gurobi 仍然读旧的。替换后一定要检查:

# 检查环境变量指向哪里
echo %GRB_LICENSE_FILE%

如果有值但路径不对,更新它:

[Environment]::SetEnvironmentVariable(
    "GRB_LICENSE_FILE",
    "C:\gurobi1300\win64\bin\gurobi.lic",
    "User"
)

6.5 许可证类型与规模限制

许可证类型来源变量数限制说明
WLS(Web License Service)pip install gurobipy 自带2000 变量, 2000 约束在线验证,有规模限制
Named-User AcademicGurobi Portal 申请无限制本地文件,免费
Named-User Commercial购买无限制本地文件,付费
Floating服务器部署无限制需 Token Server

关键区别pip install gurobipy 不带本地许可证时会自动使用 WLS,这就是为什么 C++ 能跑大规模但 Python 不行的原因。解决方法就是配置本地 .lic 文件(按上面步骤操作)。


7. gurobipy API 速查:从建模到求解的完整流程

7.1 建模五步法

所有 Gurobi 模型都遵循同一个流程:

创建模型 → 添加变量 → 添加约束 → 设置目标 → 求解
import gurobipy as gp
from gurobipy import GRB

# Step 1: 创建模型
m = gp.Model("my_model")

# Step 2: 添加变量
x = m.addVar(lb=0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="x")
y = m.addVar(lb=0, vtype=GRB.INTEGER, name="y")
z = m.addVar(vtype=GRB.BINARY, name="z")

# Step 3: 添加约束
m.addConstr(2*x + y <= 10, "c0")
m.addConstr(x + 3*y >= 4, "c1")
m.addConstr(z == 1, "c2")  # 固定 z=1

# Step 4: 设置目标
m.setObjective(x + y, GRB.MAXIMIZE)

# Step 5: 求解
m.optimize()

7.2 变量类型速查

类型vtype 参数典型用途
连续变量GRB.CONTINUOUS(默认)[lb, ub]速度、角度、质量
整数变量GRB.INTEGER[lb, ub] ∩ ℤ数量、人数
二值变量GRB.BINARY{0, 1}选择/不选择、开关
半连续变量GRB.SEMICONT{0} ∪ [lb, ub]产量为 0 或 ≥ 最低批量
半整数变量GRB.SEMIINT{0} ∪ [lb, ub] ∩ ℤ订货量为 0 或 ≥ 最低整数

批量添加变量(推荐,性能更好):

# 方法 1:addVars — 创建一组索引变量
x = m.addVars(5, lb=0, vtype=GRB.CONTINUOUS, name="x")
# 访问:x[0], x[1], ..., x[4]

# 方法 2:用列表推导 + tuplelist 索引
pairs = [(i, j) for i in range(3) for j in range(3) if i != j]
x = m.addVars(pairs, vtype=GRB.BINARY, name="x")
# 访问:x[0,1], x[0,2], x[1,0], ...

# 方法 3:字典推导(完全自定义)
indices = {"alpha": 0, "beta": 1, "gamma": 2}
y = m.addVars(indices, lb=0, ub=10, name="y")
# 访问:y["alpha"], y["beta"], y["gamma"]

7.3 约束写法大全

线性约束

# 单个约束
m.addConstr(2*x + 3*y <= 100, "capacity")

# 批量约束(用 addConstrs + 生成器表达式)
m.addConstrs((x[i] + x[j] <= 1 for i in range(5) for j in range(i+1, 5)),
             name="conflict")

# 范围约束(lhs ≤ expr ≤ rhs)
m.addRangeConstr(x + y, 5, 15, "range_c")  # 5 ≤ x+y ≤ 15

# 等式约束
m.addConstr(x + y == 10, "eq_c")

指示约束(Indicator Constraint)

二值变量控制约束是否生效——替代 Big-M 的优雅写法:

# 如果 z=1,则 x + y ≤ 10 必须满足
# 如果 z=0,则该约束被忽略
m.addConstr((z == 1) >> (x + y <= 10), "indicator_c")

SOS 约束(Special Ordered Set)

# SOS-1: 一组变量中最多 1 个非零
vars_sos = m.addVars(5, lb=0, name="sos_var")
m.addSOS(GRB.SOS_TYPE1, [vars_sos[i] for i in range(5)])

# SOS-2: 一组变量中最多 2 个相邻变量非零(分段线性近似用)
m.addSOS(GRB.SOS_TYPE2, [vars_sos[i] for i in range(5)])

通用约束(General Constraint)

# 逻辑与:z = and(x, y)
z_and = m.addVar(vtype=GRB.BINARY)
m.addConstr(z_and == gp.and_(x, y))

# 逻辑或:z = or(x, y)
z_or = m.addVar(vtype=GRB.BINARY)
m.addConstr(z_or == gp.or_(x, y))

# 最大值:z = max(x, y)
z_max = m.addVar()
m.addGenConstrMax(z_max, [x, y], name="max_c")

# 最小值:z = min(x, y)
z_min = m.addVar()
m.addGenConstrMin(z_min, [x, y], name="min_c")

# 绝对值:z = |x|
z_abs = m.addVar()
m.addGenConstrAbs(z_abs, x, name="abs_c")

# 非线性函数近似:y = f(x),用分段线性表示
import math
pts = [(i, math.sin(i)) for i in [0, 1, 2, 3]]
m.addGenConstrPWL(x, y, [p[0] for p in pts], [p[1] for p in pts])

7.4 目标函数

线性目标

m.setObjective(3*x + 2*y, GRB.MAXIMIZE)
m.setObjective(gp.quicksum(w[i]*x[i] for i in range(N)), GRB.MINIMIZE)

二次目标(QP/QCQP):

# min x^2 + y^2
m.setObjective(x*x + y*y, GRB.MINIMIZE)

多目标优化

# 先最大化目标 1,再最小化目标 2(分层优化)
m.setObjectiveN(x, index=0, priority=2, weight=1.0, name="obj1")
m.setObjectiveN(y, index=1, priority=1, weight=1.0, name="obj2")
# priority 越大越先优化

7.5 求解与结果获取

基本求解

m.optimize()

求解状态判断

if m.Status == GRB.OPTIMAL:
    print("找到最优解")
elif m.Status == GRB.INFEASIBLE:
    print("无可行解")
    m.computeIIS()  # 计算不可行子系统,找出冲突约束
    m.write("model.ilp")
elif m.Status == GRB.TIME_LIMIT:
    print("达到时间限制")
    if m.SolCount > 0:
        print(f"当前最优解: {m.ObjVal}")  # 仍有可行解
elif m.Status == GRB.UNBOUNDED:
    print("模型无界")

获取变量值

# 单个变量
val_x = x.X        # 变量值
val_rc = x.RC       # Reduced cost
val_lb = x.lb       # 下界
val_ub = x.ub       # 上界

# 批量获取
x_vals = m.getAttr("X", [x[i] for i in range(5)])
# 或
x_vals = {i: x[i].X for i in range(5)}

# 模型级信息
obj_val = m.ObjVal       # 目标函数值
gap = m.MIPGap           # MIP gap
runtime = m.Runtime      # 求解时间(秒)
node_count = m.NodeCount # 分支定界节点数

获取对偶信息(仅 LP):

# 约束的对偶值(影子价格)
constr = m.getConstrByName("c0")
pi = constr.Pi          # 对偶变量值

# 对偶值的经济含义:约束 RHS 增加 1 单位,目标函数变化 Pi 单位

7.6 常用参数设置

# 时间限制(秒)
m.setParam("TimeLimit", 3600)

# MIP Gap 容差(默认 1e-4)
m.setParam("MIPGap", 1e-6)

# 线性规划算法
m.setParam("Method", 2)     # 0=primal simplex, 1=dual simplex, 2=barrier, 3=concurrent

# 线程数
m.setParam("Threads", 8)

# 输出控制
m.setParam("OutputFlag", 0)  # 0=静默, 1=显示求解日志
m.setParam("LogFile", "solve.log")

# 求解精度
m.setParam("FeasibilityTol", 1e-6)
m.setParam("OptimalityTol", 1e-6)
m.setParam("IntFeasTol", 1e-5)

# 启发式搜索强度(MIP)
m.setParam("Heuristics", 0.5)  # 0~1,越大花越多时间在启发式

# 内存限制(GB)
m.setParam("MemLimit", 16)

参数也可以全局设置(影响所有后续创建的模型):

gp.setParam("OutputFlag", 0)   # 全局静默

7.7 模型 I/O

# 保存模型
m.write("model.lp")     # LP 格式(可读)
m.write("model.mps")    # MPS 格式(标准,跨求解器通用)
m.write("model.mst")    # MIP start 文件
m.write("model.sol")    # 解文件
m.write("model.bas")    # 基变量文件(LP)

# 读取模型
m = gp.read("model.mps")
m.optimize()

# 读取初始解(加速 MIP 求解)
m.read("initial_solution.mst")

7.8 完整示例:生产调度

一个综合示例,覆盖建模 → 求解 → 输出 → 保存全流程:

import gurobipy as gp
from gurobipy import GRB

def production_scheduling():
    """
    工厂生产调度问题:
    - 3 种产品,2 条产线
    - 每条产线有产能上限(小时)
    - 求最大利润的生产方案
    """
    products = ["A", "B", "C"]
    lines = ["L1", "L2"]

    # 利润(元/件)
    profit = {"A": 100, "B": 150, "C": 200}
    # 各产品在各产线的工时(小时/件)
    time_req = {
        ("A", "L1"): 2.0, ("A", "L2"): 2.5,
        ("B", "L1"): 1.5, ("B", "L2"): 1.0,
        ("C", "L1"): 3.0, ("C", "L2"): 2.0,
    }
    # 产线可用工时
    capacity = {"L1": 120, "L2": 100}
    # 产品最大需求
    demand = {"A": 50, "B": 80, "C": 40}

    m = gp.Model("production")
    m.setParam("OutputFlag", 0)

    # x[p, l] = 产品 p 在产线 l 上的产量
    x = m.addVars(products, lines, lb=0, vtype=GRB.INTEGER, name="x")

    # 是否生产产品 p(二值变量,用于指示约束)
    z = m.addVars(products, vtype=GRB.BINARY, name="z")

    # 约束 1:产线产能
    for l in lines:
        m.addConstr(
            gp.quicksum(time_req[p, l] * x[p, l] for p in products) <= capacity[l],
            name=f"cap_{l}"
        )

    # 约束 2:总产量 ≤ 需求
    for p in products:
        m.addConstr(
            gp.quicksum(x[p, l] for l in lines) <= demand[p],
            name=f"demand_{p}"
        )

    # 约束 3:如果 z[p]=0,则产品 p 产量为 0(指示约束)
    for p in products:
        m.addConstr(
            gp.quicksum(x[p, l] for l in lines) <= demand[p] * z[p],
            name=f"link_{p}"
        )

    # 目标:最大化利润
    m.setObjective(
        gp.quicksum(profit[p] * x[p, l] for p in products for l in lines),
        GRB.MAXIMIZE
    )

    # 求解
    m.optimize()

    # 输出结果
    if m.Status == GRB.OPTIMAL:
        print(f"最优利润: {m.ObjVal:.0f} 元")
        print(f"求解时间: {m.Runtime:.3f} 秒\n")
        print("生产方案:")
        for p in products:
            total = sum(int(x[p, l].X) for l in lines)
            if total > 0:
                detail = ", ".join(f"{l}={int(x[p,l].X)}" for l in lines)
                print(f"  产品 {p}: 共 {total} 件 ({detail})")
            else:
                print(f"  产品 {p}: 不生产")
        print(f"\n产线利用率:")
        for l in lines:
            used = sum(time_req[p, l] * x[p, l].X for p in products)
            print(f"  {l}: {used:.1f}/{capacity[l]} 小时 ({used/capacity[l]*100:.1f}%)")

        # 保存模型和解
        m.write("production.lp")
        m.write("production.sol")
    else:
        print(f"求解失败,状态码: {m.Status}")

if __name__ == "__main__":
    production_scheduling()

预期输出

最优利润: 26000 元
求解时间: 0.005 秒

生产方案:
  产品 A: 共 50 件 (L1=50, L2=0)
  产品 B: 共 80 件 (L1=0, L2=80)
  产品 C: 共 40 件 (L1=0, L2=40)

产线利用率:
  L1: 100.0/120 小时 (83.3%)
  L2: 100.0/100 小时 (100.0%)

8. 进阶:在MILP模型中使用gurobipy

以下是一个实用的论文实验模板——敏捷卫星观测调度MILP(对应球面Dubins论文Section 6.2):

import numpy as np
import gurobipy as gp

def build_transition_cost_matrix(
    Q_list: list[np.ndarray],   # N个姿态的Sabban帧 ∈ SO(3)
    dubins_solver,              # 你的球面Dubins闭式求解器
    omega_max: float,           # 卫星最大角速度 [rad/s]
) -> np.ndarray:
    """
    用球面Dubins求解器预计算精确转移时间矩阵 T_ij。
    T_ij 的每一行对应目标 i, 列对应目标 j.
    """
    N = len(Q_list)
    T = np.zeros((N, N))
    for i in range(N):
        for j in range(N):
            if i != j:
                result = dubins_solver.solve(Q_list[i], Q_list[j])
                T[i, j] = result.optimal_solution.total_angle / omega_max
    return T

def schedule_milp(
    N: int,
    T: np.ndarray,
    durations: list[float],
    time_windows: list[tuple[float, float]],
    weights: list[float],
) -> dict:
    """
    敏捷卫星多目标观测调度MILP (最大化观测总价值).

    Parameters
    ----------
    N : 目标数量
    T : (N,N) 转移时间矩阵
    durations : 每个目标的成像时长
    time_windows : 每个目标的观测时间窗 [(e_i, l_i), ...]
    weights : 每个目标的优先级权重

    Returns
    -------
    dict with keys: status, selected, sequence, start_times, total_value
    """
    m = gp.Model("agile_satellite_scheduling")
    m.setParam("OutputFlag", 0)  # 静默模式

    # --- 决策变量 ---
    x = {}  # x[i,j] = 1 表示目标i观察后立即转向目标j
    y = {}  # y[i]   = 1 表示目标i被选中观察
    t = {}  # t[i]   = 目标i的观测开始时刻

    M = 600.0  # big-M (LEO单次过顶约10分钟)

    for i in range(N):
        y[i] = m.addVar(vtype=gp.GRB.BINARY, name=f"y_{i}")
        t[i] = m.addVar(lb=0, name=f"t_{i}")
        for j in range(N):
            if i != j:
                x[i, j] = m.addVar(vtype=gp.GRB.BINARY, name=f"x_{i}_{j}")

    # --- 流守恒约束 ---
    for i in range(N):
        m.addConstr(
            gp.quicksum(x[i, j] for j in range(N) if j != i) == y[i],
            name=f"flow_out_{i}"
        )
        m.addConstr(
            gp.quicksum(x[j, i] for j in range(N) if j != i) == y[i],
            name=f"flow_in_{i}"
        )

    # --- 序列时间约束 ---
    for i in range(N):
        for j in range(N):
            if i != j:
                m.addConstr(
                    t[j] >= t[i] + durations[i] + T[i, j] - M * (1 - x[i, j]),
                    name=f"seq_{i}_{j}"
                )

    # --- 时间窗约束 ---
    for i in range(N):
        e_i, l_i = time_windows[i]
        m.addConstr(t[i] >= e_i, name=f"tw_lb_{i}")
        m.addConstr(t[i] <= l_i - durations[i], name=f"tw_ub_{i}")

    # --- 目标:最大化总价值 ---
    m.setObjective(
        gp.quicksum(weights[i] * y[i] for i in range(N)),
        gp.GRB.MAXIMIZE
    )

    m.optimize()

    # --- 结果解析 ---
    if m.Status != gp.GRB.OPTIMAL:
        return {"status": "INFEASIBLE", "selected": [], "total_value": 0.0}

    selected = [i for i in range(N) if y[i].X > 0.5]
    return {
        "status": "OPTIMAL",
        "selected": selected,
        "start_times": {i: t[i].X for i in selected},
        "total_value": m.ObjVal,
        "solve_time": m.Runtime,
    }

9. 快速故障排查清单

症状排查命令解决
gurobipy 导入失败python -c "import gurobipy"检查python -m pip list | grep gurobi
DLL载入失败python -c "import ctypes; ctypes.CDLL('gurobi130.dll')"C:\gurobi1300\win64\bin加入PATH
许可证无效python -c "import gurobipy as gp; gp.Model()"检查gurobi.lic路径和过期时间
版本不匹配python -m pip show gurobipypip install 时确认 cp312 与 Python 3.12 匹配

核心原则就一句话:python -m pip install gurobipy 保证装到当前环境,gurobi.licbin/ 下,万事大吉。 其余报错 90% 是 pip 装错了 Python 环境导致的。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐