Skip to content

[Bug]: Working with PyQt5, the different import order will make different result. #21998

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
MusYi opened this issue Dec 18, 2021 · 5 comments
Closed
Milestone

Comments

@MusYi
Copy link

MusYi commented Dec 18, 2021

Bug summary

Working with PyQt5, the different import order will make different result.

  • If import PyQt5 before import matplotlib, the program will run normally.
  • If import PyQt5 after import matplotlib, the program will riase TypeError at the method of QLayout.addWidget.

Code for reproduction

import sys

# program run correctly, if import PyQt5 here before import matplotlib
# from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget 
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
# program will raise TypeError, if import import PyQt5 after import matplotlib
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget

if __name__ == "__main__":
    app = QApplication(sys.argv)
    # init figure
    fig = Figure()
    fig_canvas = FigureCanvas(fig)
    # init widget
    layout = QVBoxLayout()
    layout.addWidget(fig_canvas) # TypeError here, if import PyQt5 after import matlpotlib
    win = QWidget()
    win.setLayout(layout)
    # run
    win.show()
    sys.exit(app.exec())

Actual outcome

TypeError
addWidget(self, QWidget, stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'FigureCanvasQTAgg'
  File "E:\CODE\Python\testroom.py", line 17, in <module>
    layout.addWidget(fig_canvas)

Expected outcome

expect no TypeError

Additional information

This Bug will not happen at the version v3.4.x of matplotlib.

Operating system

Windows

Matplotlib Version

3.5.1

Matplotlib Backend

QtAgg

Python version

Python 3.8.10

Installation

pip

@QuLogic
Copy link
Member

QuLogic commented Dec 18, 2021

Both ways work fine for me; are you certain that Matplotlib loaded PyQt5 and not PySide2?

See this explanation, but the safest way to guarantee that Matplotlib loads the intended Qt wrapper is to import it first.

@MusYi MusYi changed the title [Bug]: [Bug]: Working with PyQt5, the different import order will make different result. Dec 18, 2021
@MusYi
Copy link
Author

MusYi commented Dec 18, 2021

Thanks, I got it.

I tried it in a new python environment which just install matplotlib and pyqt5, the program will run correctlly.

So I checked the python pip environment which cause the TypeError, it contains both pyqt5 and pyside6.

At that time the matplotlib automatically import pyside6, which will conflict with the later imported pyqt5 and generate an error.

Thanks again!

@MusYi MusYi closed this as completed Dec 18, 2021
@QuLogic
Copy link
Member

QuLogic commented Dec 19, 2021

Ah yes, this would have broken in 3.5, because it added support for both Python wrappers of Qt6.

@tacaswell
Copy link
Member

I am going to re-open this, even though you can work around this by changing the import order, we should not have that sort of brittleness. I'm working on a PR to fix this.

@tacaswell tacaswell reopened this Dec 19, 2021
@tacaswell tacaswell added this to the v3.5.2 milestone Dec 19, 2021
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Dec 19, 2021
Because the code in qt_compat tries qt6 bindings first, backend_qt supports
both Qt5 and Qt6, and the qt5 named backends are shims to the generic Qt
backend, if you imported matplotlib.backends.backend_qt5agg,
matplotlib.backends.backend_qt5cairo, or matplotlib.backends.backend_qt5, and

1. had PyQt6 or pyside6 installed
2. had not previously imported a Qt5 binding

Then you will end up with a backend that (by name) claims to be Qt5, but will
be using Qt6 bindings.  If you then subsequently import a Qt6 binding and try
to embed the canvas it will fail (due to being Qt6 objects not Qt5 objects!).

closes matplotlib#21998
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Dec 19, 2021
Because the code in qt_compat tries qt6 bindings first, backend_qt supports
both Qt5 and Qt6, and the qt5 named backends are shims to the generic Qt
backend, if you imported matplotlib.backends.backend_qt5agg,
matplotlib.backends.backend_qt5cairo, or matplotlib.backends.backend_qt5, and

1. had PyQt6 or pyside6 installed
2. had not previously imported a Qt5 binding

Then you will end up with a backend that (by name) claims to be Qt5, but will
be using Qt6 bindings.  If you then subsequently import a Qt6 binding and try
to embed the canvas it will fail (due to being Qt6 objects not Qt5 objects!).

closes matplotlib#21998
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Dec 22, 2021
Because the code in qt_compat tries qt6 bindings first, backend_qt supports
both Qt5 and Qt6, and the qt5 named backends are shims to the generic Qt
backend, if you imported matplotlib.backends.backend_qt5agg,
matplotlib.backends.backend_qt5cairo, or matplotlib.backends.backend_qt5, and

1. had PyQt6 or pyside6 installed
2. had not previously imported a Qt5 binding

Then you will end up with a backend that (by name) claims to be Qt5, but will
be using Qt6 bindings.  If you then subsequently import a Qt6 binding and try
to embed the canvas it will fail (due to being Qt6 objects not Qt5 objects!).

closes matplotlib#21998
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Dec 31, 2021
Because the code in qt_compat tries qt6 bindings first, backend_qt supports
both Qt5 and Qt6, and the qt5 named backends are shims to the generic Qt
backend, if you imported matplotlib.backends.backend_qt5agg,
matplotlib.backends.backend_qt5cairo, or matplotlib.backends.backend_qt5, and

1. had PyQt6 or pyside6 installed
2. had not previously imported a Qt5 binding

Then you will end up with a backend that (by name) claims to be Qt5, but will
be using Qt6 bindings.  If you then subsequently import a Qt6 binding and try
to embed the canvas it will fail (due to being Qt6 objects not Qt5 objects!).

closes matplotlib#21998

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Jan 13, 2022
Because the code in qt_compat tries qt6 bindings first, backend_qt supports
both Qt5 and Qt6, and the qt5 named backends are shims to the generic Qt
backend, if you imported matplotlib.backends.backend_qt5agg,
matplotlib.backends.backend_qt5cairo, or matplotlib.backends.backend_qt5, and

1. had PyQt6 or pyside6 installed
2. had not previously imported a Qt5 binding

Then you will end up with a backend that (by name) claims to be Qt5, but will
be using Qt6 bindings.  If you then subsequently import a Qt6 binding and try
to embed the canvas it will fail (due to being Qt6 objects not Qt5 objects!).

Additional changes to qt_compat that only matters if

1. rcparams['backend'] is set to qt5agg or qt5agg
2. QT_API env is not set
3. the user directly import matplotlib.backends.qt_compat

This will likely only affect users who are using Matplotlib as an
qt-shim implementation.

closes matplotlib#21998

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Feb 3, 2022
Because the code in qt_compat tries qt6 bindings first, backend_qt supports
both Qt5 and Qt6, and the qt5 named backends are shims to the generic Qt
backend, if you imported matplotlib.backends.backend_qt5agg,
matplotlib.backends.backend_qt5cairo, or matplotlib.backends.backend_qt5, and

1. had PyQt6 or pyside6 installed
2. had not previously imported a Qt5 binding

Then you will end up with a backend that (by name) claims to be Qt5, but will
be using Qt6 bindings.  If you then subsequently import a Qt6 binding and try
to embed the canvas it will fail (due to being Qt6 objects not Qt5 objects!).

Additional changes to qt_compat that only matters if

1. rcparams['backend'] is set to qt5agg or qt5agg
2. QT_API env is not set
3. the user directly import matplotlib.backends.qt_compat

This will likely only affect users who are using Matplotlib as an
qt-shim implementation.

closes matplotlib#21998

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Feb 10, 2022
Because the code in qt_compat tries qt6 bindings first, backend_qt supports
both Qt5 and Qt6, and the qt5 named backends are shims to the generic Qt
backend, if you imported matplotlib.backends.backend_qt5agg,
matplotlib.backends.backend_qt5cairo, or matplotlib.backends.backend_qt5, and

1. had PyQt6 or pyside6 installed
2. had not previously imported a Qt5 binding

Then you will end up with a backend that (by name) claims to be Qt5, but will
be using Qt6 bindings.  If you then subsequently import a Qt6 binding and try
to embed the canvas it will fail (due to being Qt6 objects not Qt5 objects!).

Additional changes to qt_compat that only matters if

1. rcparams['backend'] is set to qt5agg or qt5agg
2. QT_API env is not set
3. the user directly import matplotlib.backends.qt_compat

This will likely only affect users who are using Matplotlib as an
qt-shim implementation.

closes matplotlib#21998

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Feb 11, 2022
Because the code in qt_compat tries qt6 bindings first, backend_qt supports
both Qt5 and Qt6, and the qt5 named backends are shims to the generic Qt
backend, if you imported matplotlib.backends.backend_qt5agg,
matplotlib.backends.backend_qt5cairo, or matplotlib.backends.backend_qt5, and

1. had PyQt6 or pyside6 installed
2. had not previously imported a Qt5 binding

Then you will end up with a backend that (by name) claims to be Qt5, but will
be using Qt6 bindings.  If you then subsequently import a Qt6 binding and try
to embed the canvas it will fail (due to being Qt6 objects not Qt5 objects!).

Additional changes to qt_compat that only matters if

1. rcparams['backend'] is set to qt5agg or qt5agg
2. QT_API env is not set
3. the user directly import matplotlib.backends.qt_compat

This will likely only affect users who are using Matplotlib as an
qt-shim implementation.

closes matplotlib#21998

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Mar 3, 2022
Because the code in qt_compat tries qt6 bindings first, backend_qt supports
both Qt5 and Qt6, and the qt5 named backends are shims to the generic Qt
backend, if you imported matplotlib.backends.backend_qt5agg,
matplotlib.backends.backend_qt5cairo, or matplotlib.backends.backend_qt5, and

1. had PyQt6 or pyside6 installed
2. had not previously imported a Qt5 binding

Then you will end up with a backend that (by name) claims to be Qt5, but will
be using Qt6 bindings.  If you then subsequently import a Qt6 binding and try
to embed the canvas it will fail (due to being Qt6 objects not Qt5 objects!).

Additional changes to qt_compat that only matters if

1. rcparams['backend'] is set to qt5agg or qt5agg
2. QT_API env is not set
3. the user directly import matplotlib.backends.qt_compat

This will likely only affect users who are using Matplotlib as an
qt-shim implementation.

closes matplotlib#21998

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
@QuLogic QuLogic closed this as completed in 2bc0c1c Mar 3, 2022
argilo added a commit to argilo/gnuradio that referenced this issue May 15, 2022
This works around matplotlib/matplotlib#21998 by importing
PyQt5 before matplotlib. The bug was introduced in matplotlib 3.5 and fixed in 3.5.2,
but Ubuntu 22.04 ships with 3.5.1.

Signed-off-by: Clayton Smith <argilo@gmail.com>
mormj pushed a commit to gnuradio/gnuradio that referenced this issue May 31, 2022
This works around matplotlib/matplotlib#21998 by importing
PyQt5 before matplotlib. The bug was introduced in matplotlib 3.5 and fixed in 3.5.2,
but Ubuntu 22.04 ships with 3.5.1.

Signed-off-by: Clayton Smith <argilo@gmail.com>
willcode pushed a commit to willcode/gnuradio that referenced this issue Jun 7, 2022
This works around matplotlib/matplotlib#21998 by importing
PyQt5 before matplotlib. The bug was introduced in matplotlib 3.5 and fixed in 3.5.2,
but Ubuntu 22.04 ships with 3.5.1.

Signed-off-by: Clayton Smith <argilo@gmail.com>
(cherry picked from commit 76bd672)
Signed-off-by: Jeff Long <willcode4@gmail.com>
willcode pushed a commit to willcode/gnuradio that referenced this issue Jun 7, 2022
This works around matplotlib/matplotlib#21998 by importing
PyQt5 before matplotlib. The bug was introduced in matplotlib 3.5 and fixed in 3.5.2,
but Ubuntu 22.04 ships with 3.5.1.

Signed-off-by: Clayton Smith <argilo@gmail.com>
(cherry picked from commit 76bd672)
Signed-off-by: Jeff Long <willcode4@gmail.com>
willcode pushed a commit to gnuradio/gnuradio that referenced this issue Jun 7, 2022
This works around matplotlib/matplotlib#21998 by importing
PyQt5 before matplotlib. The bug was introduced in matplotlib 3.5 and fixed in 3.5.2,
but Ubuntu 22.04 ships with 3.5.1.

Signed-off-by: Clayton Smith <argilo@gmail.com>
(cherry picked from commit 76bd672)
Signed-off-by: Jeff Long <willcode4@gmail.com>
willcode pushed a commit to gnuradio/gnuradio that referenced this issue Jun 7, 2022
This works around matplotlib/matplotlib#21998 by importing
PyQt5 before matplotlib. The bug was introduced in matplotlib 3.5 and fixed in 3.5.2,
but Ubuntu 22.04 ships with 3.5.1.

Signed-off-by: Clayton Smith <argilo@gmail.com>
(cherry picked from commit 76bd672)
Signed-off-by: Jeff Long <willcode4@gmail.com>
@weversonmachado
Copy link

Obrigado!

IvanNovakQB pushed a commit to quantum-bit/gnuradio that referenced this issue Oct 5, 2022
This works around matplotlib/matplotlib#21998 by importing
PyQt5 before matplotlib. The bug was introduced in matplotlib 3.5 and fixed in 3.5.2,
but Ubuntu 22.04 ships with 3.5.1.

Signed-off-by: Clayton Smith <argilo@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants