Recipe PyQt4 API Version

matysek edited this page Nov 11, 2014 · 1 revision

PyQt API version

PyQt4 supports two different APIs: version 1 (default on Python 2) and version 2 (default on Python 3). It is possible to change API at runtime through the sip.setapi call; a good example is that someone wants to write API v2 code on Python 2 to be future-proof and ready for the migration to Python 3.

Alas, changing API versions does not currently work with PyInstaller, and leads to error messages such as:

ValueError: API 'QString' has already been set to version 1 

Workaround for Development version

In the development version of PyInstaller a good workaround is to create a runtime hook file that is executed before the runtime hook support/rthooks/pyi_rth_qt4plugins.py in PyInstaller, and add the API changing code at the top of your custom runtime hook. Let's name the file rthook_pyqt4.py.

Then add there code:

import sip

sip.setapi(u'QDate', 2)
sip.setapi(u'QDateTime', 2)
sip.setapi(u'QString', 2)
sip.setapi(u'QTextStream', 2)
sip.setapi(u'QTime', 2)
sip.setapi(u'QUrl', 2)
sip.setapi(u'QVariant', 2)

Then rebuild your application with the --runtime-hook option

pyinstaller.py  --runtime-hook rthook_pyqt4.py  main_script.py

or add runtime_hooks argument to the Analysis object in your .spec file

a = Analysis(['main_script.py'],
              pathex=[],
              hiddenimports=[],
              hookspath=None,
              runtime_hooks=['rthook_pyqt4.py'])

and it should work with PyInstaller.

Workaround for PyInstaller 2.0

Unless the problem is fixed, a good workaround is to edit the file support/rthooks/pyi_rth_qt4plugins.py in PyInstaller, and add the API changing code at the top of it. Code like in previous section.