matplotlib / matplotlib

matplotlib: plotting with Python
https://matplotlib.org/stable/
19.93k stars 7.56k forks source link

[Bug]: Plotting code executes without displaying plots in the Console but works fine in the "Run" window #28581

Closed dododobetter closed 1 month ago

dododobetter commented 1 month ago

Bug summary

Previously, I was able to generate plots in PyCharm CE Console using Python 3.7. However, after upgrading to Python 3.11 and 3.12, the plots no longer appear in the Console. But the plots still generate successfully when running the same code in the "Run" window of PyCharm.

Code for reproduction

import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [4, 5, 6])
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.title('Example Plot')
plt.show()

Actual outcome

The Python Launcher continuously bounces in my dock and eventually becomes unresponsive.

Expected outcome

Plotting should be consistent across PyCharm environments regardless of the Python version used.

Additional information

No response

Operating system

Mac OS

Matplotlib Version

3.9.1

Matplotlib Backend

No response

Python version

3.11

Jupyter version

No response

Installation

pip

story645 commented 1 month ago

Does this happen across different versions of Matplotlib? Or is it only a 3.9 error?

tacaswell commented 1 month ago

Which backend are you using?

dododobetter commented 1 month ago

Does this happen across different versions of Matplotlib? Or is it only a 3.9 error?

This issue only happened after I upgraded Python 3.7 to 3.12 and re-installed all packages. It worked fine for Python 3.7

dododobetter commented 1 month ago

Which backend are you using?

macosx

tacaswell commented 1 month ago

Unfortunately our version numbers and Python's are overlapping at the moment. If you go to mpl38 with py312 does it work?

My suspicion is that this is related to https://matplotlib.org/stable/users/explain/figure/interactive_guide.html#input-hook-integration . The very short version is that to get "live" figures and an interactive prompt then the two infinite loop (the REPL of the prompt and the event loop of the GUI framework) need to be time-shared somehow. The story is further complicated because the behavior of plt.show() depends on some global state (controlled by plt.ion() / plt.ioff()) so in the two cases plt.show() may be doing different things. If you do plt.show(block=True) in the shell I suspect it will give you a figure, but block the prompt.

I think that this needs to be reported as a bug to pycharm.

dododobetter commented 1 month ago

Unfortunately our version numbers and Python's are overlapping at the moment. If you go to mpl38 with py312 does it work?

My suspicion is that this is related to https://matplotlib.org/stable/users/explain/figure/interactive_guide.html#input-hook-integration . The very short version is that to get "live" figures and an interactive prompt then the two infinite loop (the REPL of the prompt and the event loop of the GUI framework) need to be time-shared somehow. The story is further complicated because the behavior of plt.show() depends on some global state (controlled by plt.ion() / plt.ioff()) so in the two cases plt.show() may be doing different things. If you do plt.show(block=True) in the shell I suspect it will give you a figure, but block the prompt.

I think that this needs to be reported as a bug to pycharm.

It works now, thanks so much!! I re-installed matplotlib 3.8.0 and now the plot can show as usual from PyCharm console. I will close this ticket now.

tacaswell commented 1 month ago

I re-installed matplotlib 3.8.0 and now the plot can show as usual from PyCharm console. I will close this ticket now.

I'm going to re-open this as that identifies we had a regression between 3.8 and 3.9, but does not actually fix the problem!

tacaswell commented 1 month ago

attn @oscargus

WenkeRen commented 1 month ago

Same problem came to me. I'm happy to share some error report and my try to help the fixing.

When I'm using python=3.11, ipython==8.26.0 and matplotlib==3.9.1 Run python directly from command line: No error, plot good; Run ipython directly from command line: No error, No plot; Run ipython with pycharm: Error raised from ipython:

Traceback (most recent call last):
  File "/Users/XXX/Applications/PyCharm Professional Edition.app/Contents/plugins/python/helpers/pydev/pydev_ipython/inputhook.py", line 558, in enable_gui
    gui_hook = guis[gui]
               ~~~~^^^^^
KeyError: 'macosx'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/Users/XXX/Applications/PyCharm Professional Edition.app/Contents/plugins/python/helpers/pydev/_pydev_bundle/pydev_ipython_console_011.py", line 143, in enable_gui
    return real_enable_gui(gui, app)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/XXX/Applications/PyCharm Professional Edition.app/Contents/plugins/python/helpers/pydev/pydev_ipython/inputhook.py", line 564, in enable_gui
    raise ValueError(e)
ValueError: Invalid GUI request 'macosx', valid ones are:dict_keys(['none', 'osx', 'tk', 'gtk', 'wx', 'qt', 'qt4', 'qt5', 'qt6', 'glut', 'pyglet', 'gtk3'])
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/IPython/core/interactiveshell.py", line 3577, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-9c4300595d45>", line 4, in <module>
    plt.plot([1, 2, 3], [4, 5, 6])
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 3794, in plot
    return gca().plot(
           ^^^^^
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 2742, in gca
    return gcf().gca()
           ^^^^^
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 1093, in gcf
    return figure()
           ^^^^^^^^
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 1027, in figure
    manager = new_figure_manager(
              ^^^^^^^^^^^^^^^^^^^
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 549, in new_figure_manager
    _warn_if_gui_out_of_main_thread()
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 526, in _warn_if_gui_out_of_main_thread
    canvas_class = cast(type[FigureCanvasBase], _get_backend_mod().FigureCanvas)
                                                ^^^^^^^^^^^^^^^^^^
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 358, in _get_backend_mod
    switch_backend(rcParams._get("backend"))
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 400, in switch_backend
    switch_backend(candidate)
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 521, in switch_backend
    install_repl_displayhook()
  File "/Users/XXX/opt/anaconda3/envs/XXX/lib/python3.11/site-packages/matplotlib/pyplot.py", line 312, in install_repl_displayhook
    ip.enable_gui(ipython_gui_name)
  File "/Users/XXX/Applications/PyCharm Professional Edition.app/Contents/plugins/python/helpers/pydev/_pydev_bundle/pydev_ipython_console_011.py", line 145, in enable_gui
    raise UsageError("%s" % e)
IPython.core.error.UsageError: Invalid GUI request 'macosx', valid ones are:dict_keys(['none', 'osx', 'tk', 'gtk', 'wx', 'qt', 'qt4', 'qt5', 'qt6', 'glut', 'pyglet', 'gtk3'])

When I only downgrade matplotlib=3.8.4, everything works fine. I also tried only downgrade ipython=8.16. The errors gone but still no plot. Seems the problem comes from some incompatibility of mpl39 and ipython.

jseabold commented 1 month ago

Run ipython directly from command line: No error, No plot;

Just ran into this with ipython 8.18.1, python 3.9.5, and matplotlib 3.9.0. Wasn't sure what was going on until I found this. Downgrading matplotlib to 3.8.x worked for me.

Confirming that this does indeed show the plot from ipython and blocks with matplotlib 3.9.0.

In [1]: import matplotlib as mpl

In [2]: import matplotlib.pyplot as plt

In [3]: plt.isinteractive()
Out[3]: True

In [4]: plt.plot([0, 1], [0, 1])
Out[4]: [<matplotlib.lines.Line2D at 0x7fd4cbe48f10>]

In [5]: plt.show(block=True)
ianthomas23 commented 1 month ago

@WenkeRen When running ipython in PyCharm your error traceback states precisely what the problem is, it is expecting to use "osx" as the GUI name not the "macosx" that Matplotlib uses: https://github.com/matplotlib/matplotlib/blob/f7b3def52b39a070064e0e713042cd948c985643/lib/matplotlib/backends/registry.py#L42

IPython has to deal with this too (since Matplotlib 3.9.0, PR #27948), there is an explicit conversion at https://github.com/ipython/ipython/blob/128bd582b9894b8ae9ff577aafe13f5fdb39c3cb/IPython/core/pylabtools.py#L539-L542.

A similar change is needed in PyCharm so it needs to be reported there, it cannot be fixed here.

If you are also seeing this:

Run ipython directly from command line: No error, No plot;

then that is a separate issue. I cannot reproduce this on an M3 mac, python 3.11.9, ipython 8.26.0, matplotlib 3.9.0 or 3.9.1, using macos backend.

@jseabold Are you running this in PyCharm? I cannot reproduce this with the same python, matplotlib and ipython versions when running ipython directly from the command line.

WenkeRen commented 1 month ago

@ianthomas23 I'm so sorry. I find I cannot reproduce this problem in command line too. Probably I made some mistake at that time. So it seems the only problem is from PyCharm. Thanks for your help.

ianthomas23 commented 1 month ago

@ianthomas23 I'm so sorry. I find I cannot reproduce this problem in command line too. Probably I made some mistake at that time. So it seems the only problem is from PyCharm. Thanks for your help.

That's OK, it is good to clarify.

timhoffm commented 1 month ago

Is there something to be done on our side or can this be closed?

ianthomas23 commented 1 month ago

Is there something to be done on our side or can this be closed?

There is nothing for us to do here, it can be closed.