Keyboardinterupt does not work after a cplex model is solved
<p>I know there is a bug with Keyboardinterupts in python with multiprocessor tasks, but I also know there are some workarounds. Here I can't figure out a solution because the threads are handled inside the cplex package, which I can not (and do not want to) change.</p>

<p>Here is a minimal example:</p>

<pre><code>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&lt;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()
</code></pre>

<p>When I run this code, I can interupt the first loop, but not the second one. Once cplex has been called (and presumably multithreaded jobs have been started, but they should already be finished when I hit ctrl-C for the second time), I get '^C' printed on the screen, but I cannot interrupt the second loop.</p>

<p>Note however, that the problem does not appear when I type, in a prompt, </p>

<pre><code>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
</code></pre>

<p>So, how do I get the same behaviour as in a prompt, but in script that calls both cplex and the to-be-interrupted loop ? Any ideas ?</p>

<p>I think you may have found a bug in the CPLEX Python API.  I'm not sure yet, but I think the default signal handler is not being restored correctly there (i.e., it's corrupted once you're done with CPLEX).</p>

<p>This is a (ugly?) workaround for your specific question:</p>

<pre><code>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&lt;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)
</code></pre>

<p>This was inspired by <a href="http://bryceboe.com/2010/08/26/python-multiprocessing-and-keyboardinterrupt/" rel="nofollow">this</a> blog post, which may actually answer your larger question (how to deal with KeyboardInterrupt when using multiprocessing).</p>

python multithreading cplex keyboardinterrupt