Skip to content

Add a way to disable matplotlib interactive mode #704

Closed

Description

@IvanCobotic

Environment data

  • VS Code version: 1.59.1
  • Extension version (available under the Extensions sidebar): v2021.8.1159798656
  • OS and version: Linux x64 5.4.0-81-generic snap Ubuntu 18
  • Python version (& distribution if applicable, e.g. Anaconda): python 3.6.9 64 bit
  • Type of virtual environment used (N/A | venv | virtualenv | conda | ...): No virtual environment / N/A
  • Relevant/affected Python packages and their versions: matplotlib 3.3.4
  • Relevant/affected Python-related VS Code extensions and their versions: -
  • Value of the python.languageServer setting: Default

[NOTE: If you suspect that your issue is related to the Microsoft Python Language Server (python.languageServer: 'Microsoft'), please download our new language server Pylance from the VS Code marketplace to see if that fixes your issue]

Expected behaviour

If I run the following script by pressing run (f5), it should work as normal. The behavior when debugging should be the same regardless of what breakpoints / stepping and execution method is used. I run the code as a normal python file,
#test_plot.py

import matplotlib.pyplot as plt
plt.plot(range(10))
plt.show()

Actual behaviour

If i set a breakpoint on any of the lines above, the debugger stops on the breakpoint and the following message is printed in the integrated terminal
"Backend Qt5Agg is interactive backend. Turning interactive mode on."

If I continue the execution (with f5) the execution will not pause on the plt.show() as expected, the plot simply flashes by as a black window and the program exits.

I can verify in the debug console with
plt.isinteractive()
->True

I did however not enable interactive mode anywhere in the code.

Also, if i run (in the debug console)
plt.ioff()
This returns None, as expected, but when continuing execution with f5 the execution still will not display / pause on the plt.show() command

Steps to reproduce:

[NOTE: Self-contained, minimal reproducing code samples are extremely helpful and will expedite addressing your issue]

  1. see snippet above, just the 3 lines are needed to reproduce.

my launch.json is the default file,
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]

Logs

Output for Python in the Output panel (View→Output, change the drop-down the upper-right of the Output panel to Python)

N/A

Activity

  1. IvanCobotic commented on Aug 25, 2021

    @IvanCobotic
    Author

    I suspect this is related to
    Plots not displaying (matplotlib with TkAgg) microsoft/vscode-python#16721
    seems to be the same issue.

  2. changed the title [-]stop on breakpoint during debug enables matplotlib interactive mode[/-] [+]Stop on breakpoint during debug enables matplotlib interactive mode[/+] on Aug 25, 2021
  3. fabioz commented on Aug 25, 2021

    @fabioz
    Collaborator

    Well, the interactive mode is activated on purpose when hitting a breakpoint so that users can actually interact with the plots... if that's not done, calling plt.show() would create a plot but you wouldn't be able to see nor interact with it because the program would be paused on the breakpoint and the event loop wouldn't be running (so, the most common request is that the plots are actually interactive in the debugger -- this is the first time I saw otherwise... are you sure that's actually what you want?).

    The fact that the program finishes afterwards in your example is mostly because plt.show() is the last statement (thus, the program exits right afterwards) -- if you had some code afterwards you should be able to interact with the plot.

  4. IvanCobotic commented on Aug 25, 2021

    @IvanCobotic
    Author

    The interactive mode of matplotlib mainly refers to whether or not the program execution should pause while the plot is being displayed or if the program execution should continue. The plt.ion() is needed if one wants to create a plot and alter it programmatically from the same program. The interactive mode has its own way of working, you need to execute plt.pause(time) to get the plot to update, and typically you still want to show the plot for some time, typically done with a sleep or waitkey instruction.

    A few builds back vs code had the normal functionality. The QT backend runs in its own thread ( i think), so it was always possible to interact with the plot after executing plt.show(), regardless if you had stopped on breakpoint before hitting the plt.show() command or not. As I remember it was even possible to "step over/ f10" the plt.show() command and the interaction with the plot still worked.

    I verified this with the python debugger, if i set a breakpoint with this debugger and then run a plt.show(), like this

    <<test_plot.py>>
    import matplotlib.pyplot as plt
    plt.plot(range(10))
    print(plt.isinteractive())
    plt.show()

    in a terminal run
    pdb3 test_plot.py

    pdb will put a breakpoint and break on the first line.

    typing c to continue gives the printout
    print(plt.isinteractive()) -> False
    when plt.show() is executed the plot is displayed and it is indeed interactive in the sense that you can zoom / pan in it, but the program execution waits for you to close the plot window.

    If I do the same thing in the vs code debugger, the printout is
    print(plt.isinteractive()) -> True
    and the program execution will not wait for me to close the plot window.

    I did verify that its possible to add some code lines after plt.show() as suggested, and then the plot does display if i break on one of those lines. This however changes the way programs will execute in debug mode vs normal execution. it also changes the way you debug in vs code compared to a few builds ago. just because I put a breakpoint somewhere earlier in my code, it shouldn't alter how plt.show() behaves. I might hit the plt.show() several hundred lines later, totally unrelated to the breakpoint I had.

    Ive been working with matplotlib and vs code daily for > 1 year and never had issues with the way vs code handled plots while debugging, until the new "interactive mode is turned on" was introduced.

    If this functionality (turning interactive mode on when hitting a breakpoint) is indeed intended, I would at minimum like to see a setting to disable it. I actually cannot understand why anyone would be interested to alter the interactive mode of matplotlib based on whether or not you hit a breakpoint earlier, if you want to use interactive mode of matplotlib, why not just add a plt.ion() instruction in your code? then you will get the same execution both when debuging / normal execution, regardless of if execution previously hit a breakpoint.

  5. fabioz commented on Aug 25, 2021

    @fabioz
    Collaborator

    Disabling it through some setting seems fair... in the meanwhile, you can change the debugger locally so that the interactive mode isn't activated.

    You can do that by changing INTERACTIVE_MODE_AVAILABLE = False in pydevd_constants.

    i.e.: https://github.com/microsoft/debugpy/blob/v1.4.1/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_constants.py#L263

    You can discover where that file is in your case by running (under the debugger) the code below:

    from _pydevd_bundle import pydevd_constants
    print(pydevd_constants.__file__)
    
  6. changed the title [-]Stop on breakpoint during debug enables matplotlib interactive mode[/-] [+]Add a way to disable matplotlib interactive mode[/+] on Aug 25, 2021
  7. IvanCobotic commented on Aug 25, 2021

    @IvanCobotic
    Author

    Sweet, that worked. Thank you sir!

    I can however now confirm that the plot is indeed still interactive, even with
    INTERACTIVE_MODE_AVAILABLE = False
    I can zoom / pan etc in the plot and it is well behaved and waits for me to close it at will :)
    It even works when using F10 to step over the plt.show() command.

    But im happy with the workaround, if you want to close this issue thats fine by me.

  8. fabioz commented on Dec 4, 2021

    @fabioz
    Collaborator

    I believe that with the merge of #800 it's possible to set guiEventLoop: "none" to customize this in the launch configuration, so, I'm closing this issue (this was just integrated and it should be available for the next release).

  9. IvanCobotic commented on Jan 20, 2022

    @IvanCobotic
    Author
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions