7

I'd like python to make a plot, display it without blocking the control flow, and leave the plot open after the code exits. Is this possible?

This, and related subjects exist (see below) in numerous other threads, but I can't get the plot to both stay open, and be non-blocking. For example, if I use pyplot.ion() before pyplot.show(), or if I use pyplot.show(block=False) then the plot closes when the code terminates. This is true using either python or ipython. If it matters, I'm running on OS X 10.8.2 (Mountain Lion), running python27 and ipython27

Related discussions:
pylab matplotlib "show" waits until window closes
Is there a way to detach matplotlib plots so that the computation can continue?
Keep plotting window open in Matplotlib
Closing pyplot windows

Community
  • 1
  • 1
DilithiumMatrix
  • 17,795
  • 22
  • 77
  • 119

2 Answers2

6

On Linux you can detach the display this way:

import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import numpy as np
import os

def detach_display():
    mu, sigma = 0, 0.5
    x = np.linspace(-3, 3, 100)
    plt.plot(x, mlab.normpdf(x, mu, sigma))
    plt.show()    

if os.fork():
    # Parent
    pass
else:
    # Child
    detach_display()

The main process ends, but the plot remains.


Attempt #2. This also works on Linux; you might give it a try: but not on OS X.

import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import numpy as np
import os
import multiprocessing as mp

def detach_display():
    mu, sigma = 0, 0.5
    x = np.linspace(-3, 3, 100)
    plt.plot(x, mlab.normpdf(x, mu, sigma))
    plt.show()

proc = mp.Process(target=detach_display)
proc.start()
os._exit(0)

Without the os._exit(0), the main process blocks. Pressing Ctrl-C kills the main process, but the plot remains.

With the os._exit(0), the main process ends, but the plot remains.


Sigh. Attempt #3. If you place your matplotlib calls in another script, then you could use subprocess like this:

show.py:

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

filename = sys.argv[1]
data = np.load(filename)
plt.plot(data['x'], data['y'])
plt.show()    

test.py

import subprocess
import numpy as np
import matplotlib.mlab as mlab

mu, sigma = 0, 0.5
x = np.linspace(-3, 3, 100000)
y = mlab.normpdf(x, mu, sigma)
filename = '/tmp/data.npz'
np.savez(filename, x=x, y=y)
proc = subprocess.Popen(['python', '/path/to/show.py', filename])

Running test.py should display a plot and return control to the terminal while leaving the plot displayed.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • This gives me: `The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec(). Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug. ` – DilithiumMatrix Mar 16 '13 at 21:30
  • Apologies. Apparently this solution is Linux-specific. – unutbu Mar 16 '13 at 21:31
  • 1
    Thanks again, but still no dice. The behavior wasn't changed at all (no errors though). – DilithiumMatrix Mar 17 '13 at 22:48
-1

Although this may not directly answer the question, the easiest practical thing I have found is to (use show(block=False) and) run the script in background. That way the plot(s) remain and you are back at the shell prompt and the script exits when you kill the plot window ...

Balu
  • 537
  • 4
  • 9