25

This is a MWE of what I'm after, adapted from this question:

from matplotlib.pyplot import plot, draw, show

def make_plot():
    plot([1,2,3])
    draw()
    print 'continue computation'

print('Do something before plotting.')
# Now display plot in a window
make_plot()

answer = raw_input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')

show()

What I want is: I call the function to make the plot, the plot window appears, and then I get to go back to the prompt so I can input some value (based on that image that just displayed) and carry on with the code (the window can then close or remain there, I don't care).

What I get instead is that the window with the plot only appears after the code is completed, which is no good.


Add 1

I've tried the following with the same results, the plot window appears at the end of the code and not before:

from matplotlib.pyplot import plot, ion, draw

ion() # enables interactive mode
plot([1,2,3]) # result shows immediately (implicit draw())
# at the end call show to ensure window won't close.
draw()

answer = raw_input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')

The same happens if I change draw() for show().


Add 2

I've tried the following approach:

from multiprocessing import Process
from matplotlib.pyplot import plot, show

def plot_graph(*args):
    for data in args:
        plot(data)
    show()

p = Process(target=plot_graph, args=([1, 2, 3],))
p.start()

print 'computation continues...'

print 'Now lets wait for the graph be closed to continue...:'
p.join()

which results in a Python kernel has crashed error in Canopy with the message:

The kernel (user Python environment) has terminated with error code -6. This may be due to a bug in your code or in the kernel itself.

Output captured from the kernel process is shown below.

[IPKernelApp] To connect another client to this kernel, use:
[IPKernelApp] --existing /tmp/tmp9cshhw.json
QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries.
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python: ../../src/xcb_io.c:274: poll_for_event: La declaración `!xcb_xlib_threads_sequence_lost' no se cumple.

I should mention I'm running Canopy in elementary OS which is based in Ubuntu 12.04.


Add 3

Also tried solution posted in this question:

import numpy
from matplotlib import pyplot as plt

if __name__ == '__main__':
    x = [1, 2, 3]
    plt.ion() # turn on interactive mode
    for loop in range(0,3):
        y = numpy.dot(x, loop)
        plt.figure()
        plt.plot(x,y)
        plt.show()
        _ = raw_input("Press [enter] to continue.")

This displays empty plot windows as the code advances (ie: the user hits [enter]) and only displays the images after the code is finished.

This solution (also in the same question) doesn't even display the plot windows:

import numpy
from matplotlib import pyplot as plt
if __name__ == '__main__':
    x = [1, 2, 3]
    plt.ion() # turn on interactive mode, non-blocking `show`
    for loop in range(0,3):
        y = numpy.dot(x, loop)
        plt.figure()   # create a new figure
        plt.plot(x,y)  # plot the figure
        plt.show()     # show the figure, non-blocking
        _ = raw_input("Press [enter] to continue.") # wait for input from the user
        plt.close()    # close the figure to show the next one.
Gabriel
  • 40,504
  • 73
  • 230
  • 404

3 Answers3

28

You may use plt.show(block=False), which gets rid of the blocking directly.

For your example, this could read

from matplotlib.pyplot import plot, show

def make_plot():
    plot([1,2,3])
    show(block=False)
    print('continue computation')

print('Do something before plotting.')
# Now display plot in a window
make_plot()

answer = input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')
divenex
  • 15,176
  • 9
  • 55
  • 55
David Zwicker
  • 23,581
  • 6
  • 62
  • 77
  • 1
    This example doesn't work in my case, the plot window still appears after the code is done and not before I ask for the `answer` input. Perhaps it has something to do with my IDE (Enthought's `Canopy v 1.0.1.1190`)? – Gabriel Jun 17 '13 at 14:42
  • Ohh yeah, this feature was only added in recent matplotlib version. It works for me under matplotlib 1.2. Do you have any chance of updating? – David Zwicker Jun 17 '13 at 15:02
  • Matplotlib 1.2 is available in the Canopy package manager. This example works for me in that context on OSX-64. The window is visible though not on top... have to use the OSX "Mission Control" to reveal it, and it is unresponsive. – Jonathan March Jun 17 '13 at 15:44
  • That is indeed inconvenient. Does it perhaps work with a different backend? Such things tend to be backend-specific. – David Zwicker Jun 17 '13 at 16:25
  • So it's a no go with `Canopy`? Should I try with a different IDE? – Gabriel Jun 17 '13 at 17:09
  • 1
    I don't know much about `Canopy`, but you may just try a different backend by `import matplotlib` and `matplotlib.use('GTKAgg')` or any of the other backends to see whether it works. Note that these two lines should go before importing any other plotting related stuff. – David Zwicker Jun 18 '13 at 07:08
  • @DavidZwicker would you mind expanding a bit on what you mean by _try a different backend_? I'm pretty new to Python, sorry. – Gabriel Jun 18 '13 at 14:47
  • 1
    Here is the help from matplotlib itself: http://matplotlib.org/faq/usage_faq.html#what-is-a-backend Googling `matplotlib backend` will also point to useful threads like this: http://stackoverflow.com/questions/4930524/how-to-set-backend-in-matplotlib-in-python – David Zwicker Jun 18 '13 at 14:49
  • 1
    Late answer but sadly none of the backends worked. I'm baffled as to how it can be possible that `python` doesn't allow to show a plot _before_ ending... – Gabriel Jul 07 '13 at 00:33
14

None of the presented solutions work for me. I tested them with three different IDEs PyCharm, Spyder and Pyzo, using the (currently) latest Matplotlib 2.1 under Python 3.6.

What works for me, although not optimal, is to use a plt.pause command:

import matplotlib.pyplot as plt

def make_plot():
    plt.plot([1, 2, 3])
#    plt.show(block=False)  # The plot does not appear.
#    plt.draw()             # The plot does not appear.
    plt.pause(0.1)          # The plot properly appears.
    print('continue computation')

print('Do something before plotting.')
# Now display plot in a window
make_plot()

answer = input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')
divenex
  • 15,176
  • 9
  • 55
  • 55
  • 2
    Thank you! I know this is old, but I could not get any other solution to work, except this, and this so simple. – Jeff Sep 18 '20 at 19:38
  • 1
    I had to increase the time as I had a lot of lines to display, but this is the only solution I've found yet that works :-) – ReneBt Nov 19 '20 at 10:10
  • 1
    I gave up on this problem a long time ago, but just tried your answer and it works, thanks for that. – ajsp Oct 28 '21 at 19:24
  • Doesn't work with pause 0.1 for me. I have to increase to 0.5 which means I have to wait for a long time for the plot to appear... but at least it works. – YuseqYaseq Mar 20 '23 at 09:35
1

I couldn't get this to work with Canopy (not yet at least) but I could get the code to run sort of like I wanted to using the Geany IDE. This is the code that works for me, it's a very minor modification to the first block of code in the question where the show() command is moved above from the end of the file to just below the make_plot() command:

from matplotlib.pyplot import plot, draw, show

def make_plot():
    plot([1,2,3])
    draw()
    print 'Plot displayed, waiting for it to be closed.'

print('Do something before plotting.')
# Now display plot in a window
make_plot()
# This line was moved up <----
show()

answer = raw_input('Back to main after plot window closed? ')
if answer == 'y':
    print('Move on')
else:
    print('Nope')

It doesn't do exactly what I want but it's close enough: it shows a plot to the user, waits till that plot window is closed and then moves on with the code. Ideally it shouldn't have to wait until the plot window is closed to move on with the code, but it's better than nothing I guess.

The code in the Add 2 section above also works in the same way and with no modifications needed in Geany, but I prefer this one because it's simpler. I'll update this answer If (when?) I get this to work with Canopy.

Gabriel
  • 40,504
  • 73
  • 230
  • 404