Multiprocessing#

Demo der Verwendung von Multiprocessing zur Datengenerierung in einem Prozess und zum Plotten in einem anderen.

Geschrieben von Robert Cimrman

import multiprocessing as mp
import time

import matplotlib.pyplot as plt
import numpy as np

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

Processing Class#

Diese Klasse plottet Daten, die sie über eine Pipe empfängt.

class ProcessPlotter:
    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#

Diese Klasse verwendet Multiprocessing, um einen Prozess zu starten, der Code aus der obigen Klasse ausführt. Bei der Initialisierung erstellt sie eine Pipe und eine Instanz von ProcessPlotter, die in einem separaten Prozess ausgeführt wird.

Wenn sie von der Befehlszeile ausgeführt wird, sendet der Elternprozess Daten an den gestarteten Prozess, der dann über die in ProcessPlotter:__call__ angegebene Callback-Funktion geplottet wird.

class NBPlot:
    def __init__(self):
        self.plot_pipe, plotter_pipe = mp.Pipe()
        self.plotter = ProcessPlotter()
        self.plot_process = mp.Process(
            target=self.plotter, args=(plotter_pipe,), 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 _ in range(10):
        pl.plot()
        time.sleep(0.5)
    pl.plot(finished=True)


if __name__ == '__main__':
    if plt.get_backend() == "MacOSX":
        mp.set_start_method("forkserver")
    main()

Galerie generiert von Sphinx-Gallery