Python调用外部耗时函数时如何展示程序运行状态?
可行解决方案
1. 动态旋转光标/状态动画
不需要任何进度预估信息,纯视觉反馈,通过不断刷新控制台同一行来展示动态效果,明确告知用户程序未卡死。
示例代码:
import sys import time import threading from pyomo.environ import ConcreteModel, Var, Objective, Constraint, SolverFactory, Integers def spinning_cursor(): while not stop_event.is_set(): for cursor in '|/-\\': sys.stdout.write(f'\r求解中 {cursor}') sys.stdout.flush() time.sleep(0.2) # 替换为你的实际模型 model = ConcreteModel() model.x = Var(within=Integers) model.obj = Objective(expr=model.x**2) model.con = Constraint(expr=model.x >= 100000) # 创建线程停止控制事件 stop_event = threading.Event() # 启动动画线程 status_thread = threading.Thread(target=spinning_cursor) status_thread.start() # 调用Gurobi求解器,关闭冗余输出 solver = SolverFactory('gurobi') solver.options['OutputFlag'] = 0 results = solver.solve(model) # 停止动画线程并清理输出 stop_event.set() sys.stdout.write('\r求解完成!\n') sys.stdout.flush()
2. 利用Gurobi回调函数捕获求解状态
Gurobi支持自定义回调函数,即使关闭了默认输出,也能通过回调定期获取求解的中间状态(节点数、最优界等),既能给用户反馈,还能提供有价值的求解进度信息。
示例代码:
from pyomo.environ import ConcreteModel, Var, Objective, Constraint, SolverFactory, Integers from gurobipy import GRB import time def gurobi_status_callback(model, where): global last_print_timestamp current_time = time.time() # 每隔5秒输出一次状态,或在找到新可行解时更新 if (where == GRB.Callback.MIPSOL or where == GRB.Callback.NODE) and current_time - last_print_timestamp >= 5: node_count = model.cbGet(GRB.Callback.NODECOUNT) obj_bound = model.cbGet(GRB.Callback.BOUND) current_obj = model.cbGet(GRB.Callback.OBJBST) if where == GRB.Callback.MIPSOL else "暂未找到可行解" print(f'\r当前节点数: {node_count} | 最优界: {obj_bound:.2f} | 当前可行解目标值: {current_obj:.2f}', end='') last_print_timestamp = current_time # 替换为你的实际模型 model = ConcreteModel() model.x = Var(within=Integers) model.obj = Objective(expr=model.x**2) model.con = Constraint(expr=model.x >= 100000) solver = SolverFactory('gurobi') solver.options['OutputFlag'] = 0 last_print_timestamp = time.time() # 传递回调函数求解 results = solver.solve(model, callback=gurobi_status_callback) print('\r求解完成!最终目标值:', model.obj())
3. 后台定时心跳输出
如果不想依赖求解器的回调机制,可启动一个后台线程,每隔固定时间输出心跳信息,避免控制台长时间无输出导致用户误以为程序崩溃。
示例代码:
import threading import time import sys from pyomo.environ import ConcreteModel, Var, Objective, Constraint, SolverFactory, Integers def heartbeat_notify(): while not stop_event.is_set(): sys.stdout.write('\r程序正在求解,请稍候...') sys.stdout.flush() time.sleep(3) # 替换为你的实际模型 model = ConcreteModel() model.x = Var(within=Integers) model.obj = Objective(expr=model.x**2) model.con = Constraint(expr=model.x >= 100000) stop_event = threading.Event() heartbeat_thread = threading.Thread(target=heartbeat_notify) heartbeat_thread.start() # 执行求解 solver = SolverFactory('gurobi') solver.options['OutputFlag'] = 0 results = solver.solve(model) # 停止心跳线程并更新输出 stop_event.set() sys.stdout.write('\r求解完成!\n') sys.stdout.flush()
内容的提问来源于stack exchange,提问作者Djames
相关产品推荐
相关产品推荐

