解决复杂模型后,键盘中断不起作用

Keyboardinterupt does not work after a cplex model is solved

我知道 python 中的键盘中断在多处理器任务中存在错误,但我也知道有一些解决方法。在这里我想不出一个解决方案,因为线程是在 cplex 包内处理的,我不能(也不想)改变它。

这是一个最小的例子:

def test_interupt():
    """loops until Ctrl-C is pressed"""
    i = 0
    try:
        while True:
            i+=1
    except KeyboardInterrupt:
        print 'interrupted at i='+str(i)

def solve_dummy_cplex_problem():
    """solves the dummy optimization problem max{x|x<42}"""
    import cplex
    c = cplex.Cplex()
    c.objective.set_sense(c.objective.sense.maximize)
    c.variables.add(names=['x'], types=[c.variables.type.continuous])
    c.set_problem_type(c.problem_type.LP)
    c.linear_constraints.add(rhs=[42], senses='L', names=['cons1'])
    c.objective.set_linear( [(0,1)] )
    c.linear_constraints.set_coefficients([(0,0,1)])
    c.solve()
    print c.solution.get_values(0)

test_interupt()
solve_dummy_cplex_problem()
test_interupt()

当我运行这段代码时,我可以中断第一个循环,但不能中断第二个循环。一旦调用了 cplex(并且可能已经启动了多线程作业,但是当我第二次按下 ctrl-C 时它们应该已经完成​​),我在屏幕上打印了“^C”,但我无法中断第二个循环.

但是请注意,当我在提示中键入

时,问题不会出现
In [1]: test_interupt()
^Cinterrupted at i=213655938

In [2]: solve_dummy_cplex_problem()
Freeing MIP data.
Tried aggregator 1 time.
LP Presolve eliminated 1 rows and 1 columns.
All rows and columns eliminated.
Presolve time = 0.00 sec. (0.00 ticks)
42.0

In [3]: test_interupt()
^Cinterrupted at i=35459170

那么,如何在同时调用 cplex 和待中断循环的脚本中获得与提示中相同的行为?有什么想法吗?

我认为您可能发现了 CPLEX Python API 中的错误。我还不确定,但我认为默认信号处理程序没有在那里正确恢复(即,一旦您完成 CPLEX,它就会损坏)。

这是针对您的特定问题的(丑陋的?)解决方法:

import signal

def test_interupt(handler):
    """loops until Ctrl-C is pressed"""
    signal.signal(signal.SIGINT, handler)
    i = 0
    try:
        while True:
            i+=1
    except KeyboardInterrupt:
        print 'interrupted at i='+str(i)

def solve_dummy_cplex_problem():
    """solves the dummy optimization problem max{x|x<42}"""
    import cplex
    c = cplex.Cplex()
    c.objective.set_sense(c.objective.sense.maximize)
    c.variables.add(names=['x'], types=[c.variables.type.continuous])
    c.set_problem_type(c.problem_type.LP)
    c.linear_constraints.add(rhs=[42], senses='L', names=['cons1'])
    c.objective.set_linear( [(0,1)] )
    c.linear_constraints.set_coefficients([(0,0,1)])
    c.solve()
    print c.solution.get_values(0)

defaulthandler = signal.getsignal(signal.SIGINT)
test_interupt(defaulthandler)
solve_dummy_cplex_problem()
test_interupt(defaulthandler)

这受到了 this 博客 post 的启发,它实际上可能会回答您更大的问题(使用多处理时如何处理 KeyboardInterrupt)。