You are reading an old version of the documentation (v2.2.0). For the latest version see https://matplotlib.org/stable/gallery/misc/multiprocess_sgskip.html
Version 2.2.0
matplotlib
Fork me on GitHub

Table Of Contents

Related Topics

This Page

Multiprocess

Demo of using multiprocessing for generating data in one process and plotting in another.

Written by Robert Cimrman

from __future__ import print_function

import time
import numpy as np

from multiprocessing import Process, Pipe

# This example will likely not work with the native OSX backend.
# Uncomment the following lines to use the qt5 backend instead.
#
# import matplotlib
# matplotlib.use('qt5agg')
#
# Alternatively, with Python 3.4+ you may add the line
#
# import multiprocessing as mp; mp.set_start_method("forkserver")
#
# immediately after the ``if __name__ == "__main__"`` check.

import matplotlib.pyplot as plt

# Fixing random state for reproducibility
np.random.seed(19680801)

Processing Class

This class plots data it receives from a pipe.

class ProcessPlotter(object):
    def __init__(self):
        self.x = []
        self.y = []

    def terminate(self):
        plt.close('all')

    def call_back(self):
        while self.pipe.poll():
            command = self.pipe.recv()
            if command is None:
                self.terminate()
                return False
            else:
                self.x.append(command[0])
                self.y.append(command[1])
                self.ax.plot(self.x, self.y, 'ro')
        self.fig.canvas.draw()
        return True

    def __call__(self, pipe):
        print('starting plotter...')

        self.pipe = pipe
        self.fig, self.ax = plt.subplots()
        timer = self.fig.canvas.new_timer(interval=1000)
        timer.add_callback(self.call_back)
        timer.start()

        print('...done')
        plt.show()

Plotting class

This class uses multiprocessing to spawn a process to run code from the class above. When initialized, it creates a pipe and an instance of ProcessPlotter which will be run in a separate process.

When run from the command line, the parent process sends data to the spawned process which is then plotted via the callback function specified in ProcessPlotter:__call__.

class NBPlot(object):
    def __init__(self):
        self.plot_pipe, plotter_pipe = Pipe()
        self.plotter = ProcessPlotter()
        self.plot_process = Process(
            target=self.plotter,
            args=(plotter_pipe,)
        )
        self.plot_process.daemon = True
        self.plot_process.start()

    def plot(self, finished=False):
        send = self.plot_pipe.send
        if finished:
            send(None)
        else:
            data = np.random.random(2)
            send(data)


def main():
    pl = NBPlot()
    for ii in range(10):
        pl.plot()
        time.sleep(0.5)
    pl.plot(finished=True)


if __name__ == '__main__':
    main()

Gallery generated by Sphinx-Gallery