Abstract Factory Blog

PyQt5.1.1 for Python 2.7 [UPDATED]

30 Oct 2013

This post is about compiling PyQt5 using Python 2.7.5 on Windows 7+. As of this writing, there are no compiled versions supplied on the Riverbanks website as the author is, and I quote “doing my bit to encourage people to move to Py3″

Download PyQt5 for Python 2.7 on Windows here
Compiled against
 - Windows 7 x64
 - Visual Studio 2012
 - Python 2.7.5_x64
 - Qt 5.1.1 x64 w/ OpenGL

UPDATE – 8th Feb 2014

general error c101008d

I noticed these random errors occur during compilation of PyQt using VMWare Workstation 10. Random because they all stopped at different times with different source files blamed. Luckily, they all carried the same error message.

Turns out the error occurs due to race condition between two executables in use during compilation.

To solve this issue, I disabled all cores but one of the compilation process. As I was running under a virtual machine, I restricted it to a single-core and voilá.

UPDATE – 9th Nov 2013

Some people were having issues with the binaries-included version of this distribution.

Failed to load platform plugin "windows"

What

You’ll notice it when you try and instantiate a QApplication. It’s different from Qt 4 and the issue has to do with the modularisation of Qt 5, they’re calling it The Qt Platform Abstraction which essentially means to facilitate loose coupling between platform and application.

If you have Qt 5.1.1 installed on your machine, odds are you aren’t experiencing this issue as the plugins are included in the installation at the exact location Qt will attempt to find it.

If you don’t keep reading.

How

import os
import PyQt5
dirname = os.path.dirname(PyQt5.__file__)
plugin_path = os.path.join(dirname, 'plugins', 'platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path

Or

import os
import PyQt5
from PyQt5 import QtWidgets
dirname = os.path.dirname(PyQt5.__file__)
plugin_path = os.path.join(dirname, 'plugins', 'platforms')
QtWidgets.QApplication.addLibraryPath(plugin_path)

I have updated the link with the archive in this post. Download it again and you will see an appended “plugins” folder which contains the Platform Abstraction for Windows. Then, add the above to your code prior to importing PyQt5. It will append an environment variable that is needed under Windows.

Alternatively you may either add it to your permanent system environment or build settings if you prefer not to dilute your files.

I’ll get back regarding deployment via Pyinstaller or pywin, but I would assume a simple addition of this environment variable to their build scripts should suffice.

End Update

With much help from this youtube video as well as its author and plenty of running around the web, I finally managed to get PyQt5 up and running with my Python 2.7 setup on Windows.

Even though the video make it seem easy, there were a few more things going on in the background that wasn’t obvious to me, although I encourage you to give the video a go before reading on.

Dependencies

Riverbanks distributions hides the fact that there are any other dependencies than PyQt itself by including the dependencies in the distribution. That is great and is exactly why I’ll be doing for you when you download the result of my labour.

Qt 5

PyQt5 requires Qt 5. May seem obvious, but all PyQt is doing is mapping Python commands to the C++ version of Qt. What you get from compiling PyQt is just glue code without any actual implementation.

You’ll find that there are options as to which Qt 5.1.1 to download. To compile with VC2012, you’ll need the VC2012 one. The OpenGL option is an alternative to their default, which is equipped with ANGLE.

Get Qt here

Visual Studio 2012

There are alternatives to what you can use for compilation, in this example we’ll use VS2012.

Before you can compile, don’t forget to let VS set up your environment by running the following command:

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\Users\marcus>c:\Program Files(x86)\Microsoft Visual Studio 11.0\VC\bin\amd64\vcvars64.bat

SIP

SIP is what connects Python with C++ and is required for PyQt to run. In fact, PyQt is compiled against SIP and thus its version number is linked with your PyQt5 version and they must match. This is why your old PyQt4 won’t work unless it was also compiled against the same version of SIP. The steps to do so should be similar to those described here, but I have not tried.

Get SIP source here

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\Users\marcus> cd sip-4.15.3
C:\Users\marcus\sip-4.15.3\> python configure.py
...
C:\Users\marcus\sip-4.15.3\> nmake
...
C:\Users\marcus\sip-4.15.3\> nmake install

PyQt5

And last but not least, you’ll need the source for PyQt5.

Get PyQt5 source here
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\Users\marcus> cd PyQt-gpl-5.1.1
C:\Users\marcus\PyQt-gpl-5.1.1> python configure.py
...
C:\Users\marcus\PyQt-gpl-5.1.1> nmake
...
C:\Users\marcus\PyQt-gpl-5.1.1> nmake install

The one issue I had at this point was that I had chosen to work with the wrong bit-version of VC2012 by running vcvars32.bat rather than vcvars64.bat, having VC trying to compile a 64-bit application using a 32-bit compiler.

Additionally, if it at any points asks for qmake.exe, make sure to put your Qt bin folder on the PATH before running nmake.

C:\Users\marcus> set PATH=%PATH%;C:\Qt\5.1.1\msvc2012_64_opengl\bin

Putting it all together

At this point, you should have a working copy of PyQt5 in your site-packages folder.

To run PyQt5 on any other machine, you will have to copy the package you just made, install the re-distributable as well as Qt on the target machine. The version of Qt must match the version you compiled against.

Alternatively, you can put it all together into one nice bundle.

Simply copy the files under C:\Qt\5.1.1\msvc2012_64_opengl\bin* into your PyQt5 install directory along with the two additional files from the re-distributable - msvcp110.dll and msvcr110.dll, located in your c:\Windows\System32 folder.

The files suffixed with a “d” are for debug and can be discarded to save some space.

E.g. Qt5WebKit.dll** (20mb) – Qt5WebKitd.dll** (111mb)

What you end up with is something like this

PyQt5-5.1.1-glp-Py2.7-Qt5.1.1-x64-wbin.rar (40mb)
PyQt5-5.1.1-glp-Py2.7-Qt5.1.1-x64-wobin.rar_(7mb)

With and without binaries included respectively. Simpy extract the contents of the wbin archive into your c:\Python27\Lib\site-packages folder and you are good to go. For the more adventurous, get wobin  and use your existing installation of Qt and the VC2012 redist, just remember to put the “bin” folder of your Qt for VC2012 OpenGL on your path.

Note: If you already have PyQt4 installed, you will have to make sure you have it running with SIP version 4.15.3. You most likely aren’t, in which case I would suggest setting up a virtual environment for your PyQt5 library so that it doesn’t conflict with PyQt4.

Further reading

For those interested, figuring out which dependencies to bring along was no easy task.

depends.exe

The useful utility for looking into a dll for it’s dependencies revealed the msvcp110 and msvcr110 files was missing and a Google search revealed that they were in fact the run-time library for VS2012. Running my compiled PyQt5 on the same machine as I compiled it on worked simply because the compiler shipped with the run-time library. I suspect most software compiled with VS2012 ships with a copy of these, just like the bundle provided above does.

I said it wasn’t easy, and here’s why. Before I came to that conclusion, I made a clean install of Windows 7 on a virtual machine in hope of being able to run my newly compiled PyQt5. Alas, it gave me an error without explanation.

ImportError: DLL load failed: the specified module could not be found.

Never having encountered any such error before and never having compiled any Python library before I assumed I had failed. Never did it strike me that I had to have the binaries of Qt on my PATH at which point I cried “Eureka” out loud.

I was disappointed shortly thereafter when I found that despite Qt’s presence on another machine the error was once more given.

This was when the author of the video posted above pointed me in the right direction towards the VS2012 re-distributable.

Tying the ribbons

Not stopping there, I wanted no dependencies at all and just a single folder that I could throw around at my machines and also share with the world, and so I reset my install of Windows 7 to its original state, compared and contrasted the contents of the c:\Windows folder with original vs. after install of re-distributable only to find that the changes were few.

["Installer\\54694.msi",
"Installer\\54699.msi",
"Installer\\5469e.msi",
"Registration\\{02D4B3F1-FD88-11D1-960D-00805FC79235}.{68242296-F4D1-4E3A-A648-17817BFBF6CF}.crmlog",
"System32\\atl110.dll",
"System32\\mfc110.dll",
"System32\\mfc110chs.dll",
"System32\\mfc110cht.dll",
"System32\\mfc110deu.dll",
"System32\\mfc110enu.dll",
"System32\\mfc110esn.dll",
"System32\\mfc110fra.dll",
"System32\\mfc110ita.dll",
"System32\\mfc110jpn.dll",
"System32\\mfc110kor.dll",
"System32\\mfc110rus.dll",
"System32\\mfc110u.dll",
"System32\\mfcm110.dll",
"System32\\mfcm110u.dll",
"System32\\msvcp110.dll",
"System32\\msvcr110.dll",
"System32\\vcamp110.dll",
"System32\\vccorlib110.dll",
"System32\\vcomp110.dll",
"System32\\catroot2\\edb005CE.log",
"System32\\catroot2\\edb005CF.log",
"System32\\catroot2\\edb005D0.log",
"System32\\catroot2\\edb005D1.log",
"System32\\catroot2\\edb005D2.log",
"System32\\catroot2\\edb005D3.log",
"System32\\catroot2\\edb005D4.log",
"System32\\catroot2\\edb005D5.log",
"System32\\catroot2\\edb005D6.log",
"System32\\catroot2\\edb005D7.log",
"System32\\catroot2\\edb005D8.log",
"System32\\catroot2\\edb005D9.log",
"System32\\catroot2\\edb005DA.log",
"System32\\catroot2\\edb005DB.log",
"System32\\catroot2\\edb005DC.log",
"System32\\catroot2\\edb005DD.log",
"System32\\catroot2\\edb005DE.log",
"System32\\catroot2\\edb005DF.log",
"System32\\catroot2\\edb005E0.log",
"System32\\LogFiles\\Scm\\65dbc73f-b5cb-4223-b7e7-3f3d1b25ebdb",
"System32\\LogFiles\\Scm\\76f9461b-b67f-4717-8472-f770e565f66f",
"System32\\SMI\\Store\\Machine\\SCHEMA.DAT{bdf69758-4015-11e3-bda3-844bf534180e}.TM.blf",
"System32\\SMI\\Store\\Machine\\SCHEMA.DAT{bdf69758-4015-11e3-bda3-844bf534180e}.TMContainer00000000000000000001.regtrans-ms",
"System32\\SMI\\Store\\Machine\\SCHEMA.DAT{bdf69758-4015-11e3-bda3-844bf534180e}.TMContainer00000000000000000002.regtrans-ms"]

Aha! Realising that there was nothing in this list except for the two files I had previously seen missing via the depends.exe utility it became obvious that including just these two additional dependencies into my bundle was all that was required for a fully contained copy of PyQt5 for Python 2.7.5.

Happy compiling!