Repository navigation
Add a way to disable matplotlib interactive mode #704
Description
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.languageServersetting: 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]
- 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
IvanCobotic commentedon Aug 25, 2021
I suspect this is related to
Plots not displaying (matplotlib with TkAgg) microsoft/vscode-python#16721
seems to be the same issue.
[-]stop on breakpoint during debug enables matplotlib interactive mode[/-][+]Stop on breakpoint during debug enables matplotlib interactive mode[/+]fabioz commentedon Aug 25, 2021
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.IvanCobotic commentedon Aug 25, 2021
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.
fabioz commentedon Aug 25, 2021
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 = Falseinpydevd_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:
[-]Stop on breakpoint during debug enables matplotlib interactive mode[/-][+]Add a way to disable matplotlib interactive mode[/+]IvanCobotic commentedon Aug 25, 2021
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.
fabioz commentedon Dec 4, 2021
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).IvanCobotic commentedon Jan 20, 2022