{
"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
}