In Python, I would like to have the main output windows printing output continuously but also launch a matplotlib graph that shows the same data in a parallel process. I want the user to be able to close the graph and re-open as they wish but always have the output window printing the new data without pausing. I want it to be a parallel process because I want the main output window to keep updating.
I am new to Python and multiprocessing so apologies if I am not explaining things precisely.
__
Whenever I run the example script below and close the graph, the main output window asks if I want to restart the graph, as expected, but when I type 'y', I get an error that I cannot restart the process:
assert self._popen is None, 'cannot start a process twice'
AssertionError: cannot start a process twice`
Example script.
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from multiprocessing import Process, Pipe
import multiprocessing
import time
import random
# Shows matplotlib graph that updates based on "generate_data" function
def show_graph(connection):
fig, ax = plt.subplots()
line, = plt.plot([], [], 'r-')
def init():
ax.set_xlim(0, 30)
ax.set_ylim(0, 30)
return line,
def update(frame):
[x,y] = connection.recv()
line.set_data(x, y)
return line,
ani = FuncAnimation(fig, update, frames=None, init_func=init, blit=True)
plt.show()
# Function that obtains data to plot
def generate_data():
x = random.sample(range(0, 30), 20)
y = random.sample(range(0, 30), 20)
return x, y
if __name__ == "__main__":
parent_conn, child_conn = Pipe()
plot_process = multiprocessing.Process(target=show_graph, args=(child_conn,))
plot_process.start()
while True:
time.sleep(0.5)
x, y = generate_data()
# Display data in main output window
print(x)
print(y)
if plot_process.is_alive():
parent_conn.send([x,y])
else:
name = input("Graphing process is dead! Restart graph?")
if name == "y":
plot_process.start()
As the error says, you cannot start the same process twice. You should terminate it so that you can start it again with plot_process.terminate() and wait for it to actually terminate with plot_process.join() before starting it again.
if name == "y":
plot_process.terminate()
plot_process.join()
plot_process = multiprocessing.Process(target=show_graph, args=(child_conn,))
plot_process.start()