exit on KeyboardInterrupt after generating plots in while loop
Asked Answered
C

2

6

I am monitoring an experiment in real time using matplotlib to generate plots in a while loop. Ideally, the loop should exit on something like a KeyboardInterrupt. This works well enough in an Ubuntu test. In Windows 7, using ipython, it exits with "Terminate batch job (Y/N)?" then closes the interpreter. I would like to avoid this behavior and leave the interpreter open after the KeyboardInterrupt. Here is a test script.

[EDIT 2]: This script works fine in Windows if ipython is loaded as ipython --pylab.

import time
import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot([0], [0], 'b-o')

window = 50
plot_data = np.zeros((window, 2))

i = 0
start = time.time()
while True:
    try:
        data = [time.time() - start, np.random.rand()]
        print ' '.join('{:.2f}'.format(x) for x in data)
        if i < window:
            plot_data[i,:] = data
            line.set_data(plot_data[0:i+1,0], plot_data[0:i+1,1])
        else:
            plot_data[0:window-1] = plot_data[1:window]
            plot_data[window-1] = data
            line.set_data(plot_data[:,0], plot_data[:,1])
        ax.relim()
        ax.autoscale_view(True,True,True)
        fig.canvas.draw()
        plt.pause(0.1)
        i += 1
    except KeyboardInterrupt:
            print "Program ended by user.\n"
            break 
print 'Success!'

[EDIT 1]: I should be more clear why I tagged this with matplotlib. The below example script executes with no problems in either operating system.

i = 0 
start = time.time()
while True:
    try:
        data = [time.time() - start, np.random.rand()]
        print ' '.join('{:.2f}'.format(x) for x in data)
        time.sleep(0.1)
    except KeyboardInterrupt:
        print "Proram ended by user. \n"
        break
print 'Success!'

All of the packages were installed yesterday as part of a clean installation of Enthought.

Calcariferous answered 7/1, 2013 at 16:31 Comment(1)
Part of the issue is specifically that plt.pause is not interruptible while there is a figure drawn (not a Windows-specific bug). I would recommend bringing this up as a matplotlib IssueOswaldooswalt
C
1

Right now the best way I've found to solve this problem across several Windows machines is as follows...

print 'press \'q\' to end run'
time.sleep(1.0)

fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot([0], [0], 'b-o')

window = 150
plot_data = np.zeros((window, 2))

i = 0
start = time.time()
while True:
    data = [time.time() - start, np.random.rand()]
    print ' '.join('{:.2f}'.format(x) for x in data)
    if i < window:
        plot_data[i,:] = data
        line.set_data(plot_data[0:i+1,0], plot_data[0:i+1,1])
    else:
        plot_data[0:window-1] = plot_data[1:window]
        plot_data[window-1] = data
        line.set_data(plot_data[:,0], plot_data[:,1])
    ax.relim()
    ax.autoscale_view(True,True,True)
    fig.canvas.draw()
    plt.pause(delay)
    i += 1
    if msvcrt.kbhit():
        if ord(msvcrt.getch()) == 113:
            print "Program ended by user.\n"
            break 
print 'Success!'

Unfortunately, this is not at all platform independent, but everything I've read over the past few days leads me to believe that platform-independent keyboard input is not really achievable. The code in my original question works well in Unix and some Windows installations. This code works well in the few Windows installations I've tried. All of this works best when run through ipython --pylab. This might have to be good enough for now.

Calcariferous answered 8/1, 2013 at 21:15 Comment(0)
E
0

I cannot reproduce your problem. I copied your test script in a file ipythonexception.py and started it from ipython with the run command. Then I get the following output.

In [1]: run ipythonexception.py
0.00 0.27
0.31 0.11
0.56 0.44
0.81 0.26
1.06 0.27
1.29 0.66
1.53 0.32
1.76 0.74
2.03 0.44
2.26 0.89
Program ended by user.

Success!

In [2]: window
Out[2]: 50

In [3]:

Everything seems to work as it should do. I'm on Windows 7, Python 2.7.2 and Ipython 0.13.

Do you start Ipython with a batch file? I tink "Terminate batch job (Y/N)?" is a Windows message I usually get if I break some batch jobs.

Elsy answered 8/1, 2013 at 8:48 Comment(2)
I suspect this problem has something to do with the way Enthought and ipython work together. I also could not reproduce the problem outside of my Enthought installation. It seems that Enthought might open ipython as part of a batch script. When opening with ipython --pylab I don't get a "Terminate batch job (Y/N)?" message immediately after running that test script, but I do get the message upon quitting ipython with quit(). I think this link may be related: linkCalcariferous
I did confirm this on a second Enthought installation in our lab. This one is on an XP SP3 machine. It seems like the best answer for this is to just avoid using KeyboardInterrupt to end the program.Calcariferous

© 2022 - 2024 — McMap. All rights reserved.