0

Please consider this code which start two threads. Each of these threads execute python codes : create a plot, some labeling and show figure. These codes are executed in main thread as Matplotlib requires.

import queue
import threading


def runScriptMainThread(code):
    print(threading.current_thread())
    print("Code : ", code)
    exec(code)


def runScript(code):
    callback_queue.put(lambda: runScriptMainThread(code))


callback_queue = queue.Queue()
threading.Thread(target=runScript, args=("import matplotlib.pyplot as plt;plt.plot([1, 2, 3, 4]);plt.ylabel('some numbers');plt.show(block=True);",)).start()
threading.Thread(target=runScript, args=("import matplotlib.pyplot as plt;plt.plot([5, 6, 3, 4]);plt.ylabel('some numbers');plt.show(block=True);",)).start()

while True:
    try:
        callback = callback_queue.get(block=False)
        callback()
        print("After callback")
    except queue.Empty:  # raised when queue is empty
        print("Empty")

Executing this code will produce this output :

<_MainThread(MainThread, started 4525688320)>
Code :  import matplotlib.pyplot as plt;plt.plot([1, 2, 3, 4]);plt.ylabel('some numbers');plt.show(block=True);
After callback
<_MainThread(MainThread, started 4525688320)>
Code :  import matplotlib.pyplot as plt;plt.plot([5, 6, 3, 4]);plt.ylabel('some numbers');plt.show(block=True);
After callback
Empty
Empty
...

First code from first thread is executed and when matplotlib figure is closed second code from second thread is executed and show second figure. But when this second figure is closed, its window is stucked and always visible : it does not disappear.

Do you know how to properly close this final window ?

MacOSX 12.6

Python 3.9

Matplotlib 3.4.1

PyCharm CE 2022.1 (Build #PC-221.5080.212, built on April 12, 2022)

PS : I am using py4j running python code from Java. This is why I am dealing with multiple threads.

frank b.
  • 55
  • 10

1 Answers1

0

Since you're running all the matplotlib code on the main thread, I'd guess that the problem isn't related to the threading code. I suggest you try this simplified script to see if it behaves the same way as yours.

import matplotlib.pyplot as plt

def plot_numbers(numbers):
    plt.plot(numbers)
    plt.ylabel('some numbers')
    plt.show(block=True)

plot_numbers([1, 2, 3, 4])
plot_numbers([5, 6, 3, 4])
while True:
    print('Empty')

If it behaves the same, then I suspect you have run into a problem with one of the MacOS backends to matplotlib. Try switching to a different backend, as described in this post.

FYI, I don't see the problem when I try running your code or my simplified code on Ubuntu 20.04 with Python 3.9 and matplotlib 3.6.0.

Don Kirkby
  • 53,582
  • 27
  • 205
  • 286
  • As it is mentioned in Question's PS, I'm dealing with multiple threads as I'm using py4j to run python code from Java : this code is never launched from main python thread. This is why I'm simulating multithreading in question code example. And as you can see in question comment, updating to matplotlib 3.6.2 solved the problem. Thks for your reply Don. – frank b. Jan 02 '23 at 18:44