PyQt4 and PyQt5 collisions in PyCharm 2017.2.1 when debugging QGIS application

Completed

I am using PyCharm 2017.2.1. When debugging a python script in PyCharm, upon hitting the first breakpoint, I see this traceback in the console:

Failed to enable GUI event loop integration for 'qt5'
Traceback (most recent call last):
  File "/opt/pycharm-community/helpers/pydev/pydev_ipython/matplotlibtools.py", line 31, in do_enable_gui
    enable_gui(guiname)
  File "/opt/pycharm-community/helpers/pydev/pydev_ipython/inputhook.py", line 528, in enable_gui
    return gui_hook(app)
  File "/opt/pycharm-community/helpers/pydev/pydev_ipython/inputhook.py", line 214, in enable_qt5
    from pydev_ipython.inputhookqt5 import create_inputhook_qt5
  File "/opt/pycharm-community/helpers/pydev/pydev_ipython/inputhookqt5.py", line 25, in <module>
    from PyQt5 import QtCore, QtGui
RuntimeError: the PyQt5.QtCore and PyQt4.QtCore modules both wrap the QObject class
Backend Qt5Agg is interactive backend. Turning interactive mode on.

I am not specifically importing matplotlib or PyQt, and I have PyQt4 configured in the debugger. If I turn off PyQt support in the debugger entirely, I get this traceback:

Backend Qt5Agg is interactive backend. Turning interactive mode on.
Failed to enable GUI event loop integration for 'qt5'
Traceback (most recent call last):
  File "/opt/pycharm-community/helpers/pydev/pydev_ipython/matplotlibtools.py", line 31, in do_enable_gui
    enable_gui(guiname)
  File "/opt/pycharm-community/helpers/pydev/pydev_ipython/inputhook.py", line 528, in enable_gui
    return gui_hook(app)
  File "/opt/pycharm-community/helpers/pydev/pydev_ipython/inputhook.py", line 214, in enable_qt5
    from pydev_ipython.inputhookqt5 import create_inputhook_qt5
  File "/usr/share/qgis/python/qgis/utils.py", line 607, in _import
    mod = _builtin_import(name, globals, locals, fromlist, level)
  File "/opt/pycharm-community/helpers/pydev/pydev_ipython/inputhookqt5.py", line 25, in <module>
    from PyQt5 import QtCore, QtGui
  File "/usr/share/qgis/python/qgis/utils.py", line 607, in _import
    mod = _builtin_import(name, globals, locals, fromlist, level)
RuntimeError: the PyQt5.QtCore and PyQt4.QtCore modules both wrap the QObject class

The message "Backend Qt5Agg is interactive backend. Turning interactive mode on." is coming from matplotlib. I've included it with the traceback to show that it appears before the traceback when PyQt support is turned off, and after the traceback when PyQt support is turned on. (Note also that qgis' utils.py appears in the traceback with PyQt support off.)

This occurs only when debugging. The script completes without errors when executed normally.

After hitting the breakpoint, I cannot step through the code; using "Step into" results in execution continuing until the next breakpoint is hit.

 

3 comments

I have resolved the problem. Here is how I did so.

A dependency of my code loads matplotlib, which causes the pycharm debugger to load its internal module matplotlibtools.py. This attempts to enable the GUI interactive event loop via the do_enable_gui function:

import sys

backends = {'tk': 'TkAgg',
'gtk': 'GTKAgg',
'wx': 'WXAgg',
'qt': 'Qt4Agg', # qt3 not supported
'qt4': 'Qt4Agg',
'qt5': 'Qt5Agg',
'osx': 'MacOSX'}

# We also need a reverse backends2guis mapping that will properly choose which
# GUI support to activate based on the desired matplotlib backend. For the
# most part it's just a reverse of the above dict, but we also need to add a
# few others that map to the same GUI manually:
backend2gui = dict(zip(backends.values(), backends.keys()))
backend2gui['Qt4Agg'] = 'qt4'
backend2gui['Qt5Agg'] = 'qt5'
# In the reverse mapping, there are a few extra valid matplotlib backends that
# map to the same GUI support
backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
backend2gui['WX'] = 'wx'
backend2gui['CocoaAgg'] = 'osx'


def do_enable_gui(guiname):
from _pydev_bundle.pydev_versioncheck import versionok_for_gui
if versionok_for_gui():
try:
from pydev_ipython.inputhook import enable_gui
enable_gui(guiname)
except:
sys.stderr.write("Failed to enable GUI event loop integration for '%s'\n" % guiname)
import traceback
traceback.print_exc()
elif guiname not in ['none', '', None]:
# Only print a warning if the guiname was going to do something
sys.stderr.write("Debug console: Python version does not support GUI event loop integration for '%s'\n" % guiname)
# Return value does not matter, so return back what was sent
return guiname

The backend is determined by the system default. It turns out that it is sufficient to set the backend explicitly in code to avoid this error. Adding

import matplotlib
matplotlib.rcParams['backend'] = 'Qt4Agg'
matplotlib.rcParams['backend.qt4'] = 'PyQt4'

to the beginning of my main module resolves the issue.

1

On Ubuntu 16.04.3 LTS with installed the following versions of Qt:

qt4-x86_64-linux-gnu
qt5-x86_64-linux-gnu

I had to change Qt4 to Qt5:


import matplotlib
matplotlib.rcParams['backend'] = 'Qt5Agg'
matplotlib.rcParams['backend.qt5'] = 'PyQt5'
0

Dear colleagues,

Please Help.

 

1. I add Path according to instruction https://github.com/USEPA/SWMM-EPANET_User_Interface/wiki/Getting-Started-as-a-Developer-in-Python-3

If I start and try import qgis I receive error: 

 

2. I start with python-qgis.bat file with:

@echo off
call C:\OSGeo4W64\bin\o4w_env.bat
call qt5_env.bat
call py3_env.bat
@echo off
path %OSGEO4W_ROOT%\apps\qgis\bin;%PATH%;
set QGIS_PREFIX_PATH=%OSGEO4W_ROOT:\=/%/apps/qgis
set GDAL_FILENAME_IS_UTF8=YES
rem Set VSI cache to be used as buffer, see #6448
set VSI_CACHE=TRUE
set VSI_CACHE_SIZE=1000000
set QT_PLUGIN_PATH=%OSGEO4W_ROOT%\apps\qgis\qtplugins;%OSGEO4W_ROOT%\apps\qt5\plugins
set PYTHONPATH=%OSGEO4W_ROOT%\apps\qgis\python;%PYTHONPATH%;
rem "%PYTHONHOME%\python" %*

@"C:\Program Files\JetBrains\PyCharm 2018.2\bin\pycharm64.exe"

 

Then I run program with Ctr+Shift+F10 everything is ok, program run. 

But if I try start debugging I received error:

Please help...

 

Thanks in advance!

0

Please sign in to leave a comment.