|
|
|||||||||||||||||||||||||||||
|
matplotlib misc_Examples 05_multiprocess. |
H.Kamifuji . |
1 つのプロセスでデータを生成し、別のプロセスでプロットするためのマルチプロセッシングのデモ Robert Cimrman 著
# -*- noplot -*-
# 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
from multiprocessing import Process, Pipe
import numpy as np
import matplotlib
matplotlib.use('GtkAgg')
import matplotlib.pyplot as plt
import gobject
class ProcessPlotter(object):
def __init__(self):
self.x = []
self.y = []
def terminate(self):
plt.close('all')
def poll_draw(self):
def call_back():
while 1:
if not self.pipe.poll():
break
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
return call_back
def __call__(self, pipe):
print('starting plotter...')
self.pipe = pipe
self.fig, self.ax = plt.subplots()
self.gid = gobject.timeout_add(1000, self.poll_draw())
print('...done')
plt.show()
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)
try:
input = raw_input
except NameError:
pass
input('press Enter...')
pl.plot(finished=True)
if __name__ == '__main__':
main()
|
当方の環境では、動作しない。出力 msg は、下記$ py multiprocess.py Traceback (most recent call last): File "multiprocess.py", line 12, inPython 3.11.2 見直しました。上記のコードでは、下記のエラーが発生します。 Traceback (most recent call last): File "_:\multiprocess.py", line 12, in <modulegt; matplotlib.use('GtkAgg') File "C:\Users\_____\AppData\Local\Programs\Python\Python311\Lib\site-packages\matplotlib\__init__.py", line 1234, in use name = validate_backend(backend) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\_____\AppData\Local\Programs\Python\Python311\Lib\site-packages\matplotlib\rcsetup.py", line 252, in validate_backend else _validate_standard_backends(s)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\_____\AppData\Local\Programs\Python\Python311\Lib\site-packages\matplotlib\rcsetup.py", line 82, in __call__ raise ValueError(msg) ValueError: 'gtkagg' is not a valid value for backend; supported values are ['GTK3Agg', 'GTK3Cairo', 'GTK4Agg', 'GTK4Cairo', 'MacOSX', 'nbAgg', 'QtAgg', 'QtCairo', 'Qt5Agg', 'Qt5Cairo', 'TkAgg', 'TkCairo', 'WebAgg', 'WX', 'WXAgg', 'WXCairo', 'agg', 'cairo', 'pdf', 'pgf', 'ps', 'svg', 'template'] matplotlib 内部のエラーのようです。matplotlib の改修(先祖帰りバグの改修)を待つしかない。 Python 3.11.6 (matplotlib 3.7.1) では、下記のようなエラーがあり、実行できない。 Traceback (most recent call last): File "M:\______\multiprocess.py", line 12, inPython 3.12.0 (matplotlib 3.8.1) では、下記のようなエラーがあり、実行できない。 Traceback (most recent call last): File "E:\______\multiprocess.py", line 12, inPython 3.11.6 (matplotlib 3.7.1) 及び Python 3.12.0 (matplotlib 3.8.1) で、見直し中、新しいサンプル(misc-multiprocess-sgskip-py) を見つけ、下記のコードで、正常に実行できました。
"""
===============
Multiprocessing
===============
Demo of using multiprocessing for generating data in one process and
plotting in another.
Written by 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
# ================
#
# This class plots data it receives from a pipe.
#
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
# ==============
#
# 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:
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()
Python 3.11.6 (matplotlib 3.7.1) 及び Python 3.12.0 (matplotlib 3.8.1) 共に、正常実行です。![]() ![]() ![]() |
|
misc_Examples code: multiprocess.py misc-multiprocess-sgskip-py |
|