{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Multiprocessing\n\nDemo of using multiprocessing for generating data in one process and\nplotting in another.\n\nWritten by Robert Cimrman\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import multiprocessing as mp\nimport time\n\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Fixing random state for reproducibility\nnp.random.seed(19680801)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Processing Class\n\nThis class plots data it receives from a pipe.\n\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "class ProcessPlotter:\n def __init__(self):\n self.x = []\n self.y = []\n\n def terminate(self):\n plt.close('all')\n\n def call_back(self):\n while self.pipe.poll():\n command = self.pipe.recv()\n if command is None:\n self.terminate()\n return False\n else:\n self.x.append(command[0])\n self.y.append(command[1])\n self.ax.plot(self.x, self.y, 'ro')\n self.fig.canvas.draw()\n return True\n\n def __call__(self, pipe):\n print('starting plotter...')\n\n self.pipe = pipe\n self.fig, self.ax = plt.subplots()\n timer = self.fig.canvas.new_timer(interval=1000)\n timer.add_callback(self.call_back)\n timer.start()\n\n print('...done')\n plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotting class\n\nThis class uses multiprocessing to spawn a process to run code from the\nclass above. When initialized, it creates a pipe and an instance of\n``ProcessPlotter`` which will be run in a separate process.\n\nWhen run from the command line, the parent process sends data to the spawned\nprocess which is then plotted via the callback function specified in\n``ProcessPlotter:__call__``.\n\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "class NBPlot:\n def __init__(self):\n self.plot_pipe, plotter_pipe = mp.Pipe()\n self.plotter = ProcessPlotter()\n self.plot_process = mp.Process(\n target=self.plotter, args=(plotter_pipe,), daemon=True)\n self.plot_process.start()\n\n def plot(self, finished=False):\n send = self.plot_pipe.send\n if finished:\n send(None)\n else:\n data = np.random.random(2)\n send(data)\n\n\ndef main():\n pl = NBPlot()\n for _ in range(10):\n pl.plot()\n time.sleep(0.5)\n pl.plot(finished=True)\n\n\nif __name__ == '__main__':\n if plt.get_backend() == \"MacOSX\":\n mp.set_start_method(\"forkserver\")\n main()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }