I have a function which plots a figure
import matplotlib.pyplot as plt
def myplot(x, y):
plt.figure()
plt.plot(x, y)
plt.show()
myplot([1, 2, 3], [4, 5, 6])
myplot([1, 2, 3], [4, 5, 6])
However after I run the script only one figure shows up, and the second one shows when I close the first figure. I can move plt.show()
into main
function which calls myplot
and this works fine, but I still want a better way, just like plot
in Matlab. Thank you in advance.
CodePudding user response:
this is not a simple thing, as Matlab is already running a GUI eventloop, while for python ... it depends on the IDE, for example Spyder will run it similar to Matlab as it is running an event loop, while Pycharm / VScode don't allow python to snatch their event loop, and jupyter notebook is running an asyncio server which sends the data to your browser so it can do it but it's not the same as Matlab .... so it depends on your IDE.
now assuming that you are running an interactive session inside your terminal ... or any IDE like IDLE, you can create another process that will be running that eventloop using loky, that has to run inside a thread ...
import matplotlib.pyplot as plt
import threading
from loky import ProcessPoolExecutor
import traceback
def myplot(*args,**kwargs):
thread = threading.Thread(target=threaded_func,args=args,kwargs=kwargs,daemon=False)
thread.start()
def threaded_func(*args,**kwargs):
try:
with ProcessPoolExecutor(max_workers=1) as executor:
res = executor.submit(plotting_func,*args,**kwargs)
res.result()
except RuntimeError as e:
pass
def plotting_func(*args,**kwargs):
try:
plt.figure()
plt.plot(*args,**kwargs)
plt.show()
except Exception as e:
traceback.print_exc()
myplot([1, 2, 3], [4, 5, 6])
myplot([1, 2, 3], [4, 5, 6])
this is obviously not perfect as you can only modify your plots inside your plotting_func
, not inside your interactive code as Matlab does, and while there are ways to get some code working as expected, it really depends on the exact use-case, not a generic code like yours.
for example you can have matplotlib running a temporary eventloop in interactive mode.
import matplotlib.pyplot as plt
plt.ion() # activate interactive mode
def myplot(x, y):
plt.figure()
plt.plot(x, y)
plt.show()
myplot([1, 2, 3], [4, 5, 6])
myplot([1, 2, 3], [4, 5, 6])
plt.pause(5) # run eventloop for 5 seconds
now everytime you want the plot to update you just call
plt.pause(5)
which will run the eventloop for 5 seconds for you to inspect the plot, and you can interactively modify it like matlab, but this is just a band-aid, and you have to think about writing python code that's not mirrored matlab code.