[PyKDE] Static compilation of PyQt

Phil Thompson phil at riverbankcomputing.co.uk
Fri Mar 3 08:57:50 GMT 2006

On Thursday 02 March 2006 11:31 am, Giovanni Bajo wrote:
> Hello,
> For the past few months, I have been using a statically-compiled version of
> PyQt. "Statically" here means that it's still an external module (.pyd) but
> it does not depend on the external C++ Qt DLL: the module is totally
> self-contained. This bring several advantages:
> - Size. A static version of PyQt (snapshots of December) with Qt 3.3.5, and
> modules Core + OpenGL, is 1.1 Mb (compressed with UPX). When using Core +
> OpenGL + Canvas + Table, size is 1.3 Mb. The size win is given by the
> saving of almost 1,5 Mb of import and export sections (respectively in
> qt.pyd and qt-mt335.dll), which are not necessary anymore. The sections are
> *very* large because C++ name mangling is bloated as we all know.
> - Ease of mainteance. A single file is easier to update, copy around, and
> whatnot. I have several versions of PyQt and Qt in my computer and I don't
> have to wonder anymore which version of PyQt goes with which Qt DLL.
> - Minor startup speed benefit. A *cold* import of PyQt on my computer is
> now roughly twice as faster than before (0.4 seconds instead of 0.9
> seconds). "Cold" import means after flushing all disk caches. Notice that
> this is the time which matters most for users as they tipically don't
> execute GUI applications many times in a row and thus they do not benefit
> from OS caching.
> It also brings a couple of disadvantages:
> - Change of API. Since you need to have a single file qt.pyd with all the
> modules in it, there are name changes in the application. For instance
> QTable is imported from "qt" and not "qttable". This doesn't matter much if
> you use the "from qt import *" syntax, but it still poses a compatibility
> problem (existing code using "from qttable import *" won't work).
> I would like to stress that the size improvement is a very good sell point
> for PyQt4/Win. Currently, users shipping Python GUI applications under
> Windows (with tools like PyInstaller and py2exe) always complain of the
> fact that the final size of the application is too large (especially
> compared with the small Python source code that produces it). wxWidgets is
> a huge bloat of some 10Mb, for instance, but given that Qt3 wasn't free for
> Windows there weren't many options for free development. With the advent of
> Qt4 and PyQt4, I'm sure many will evaluate PyQt4, and will surely look at
> the distribution size.
> Alas, I haven't looked into PyQt4 yet (and still won't for some months), so
> I can't really contribute a patch for there. But I do have a script to
> compile PyQt3 statically which I'm willing to contribute. I would like this
> to become part of the official build system for PyQt. Notice that currently
> compiling PyQt with a statically-compiled Qt leads to a crash if you use
> more modules (as each pyd, eg. qttable.pyd, will contain a full copy of the
> Qt C++ code). So this might simply be the default way of building PyQt when
> a statically-compiled Qt is detected.
> BTW, for PyQt3, the steps are really easy:
> 1) Compile Qt statically (produce qt-mt.lib)
> 2) Merge all the modules of PyQt you're interested in into qtmod.sip (you
> *must* build only qt.pyd).
> 3) Build qt.pyd only.
> I have a Python script which does the module merging.

I think this is a good idea, but...

1. Changing the API isn't acceptable, "import qttable" must continue to work.

2. I don't want to do this for PyQt3 - unless doing it for PyQt4 makes it 
trivial to do for PyQt3. The primary beneficiary will be Windows GPL users.

You can solve 1. by flipping Gerard's idea around for Qt.py and generating a 
qttable.py that contained...

from qt import QTable, QTableItem, ...

The problem with this is that this is probably better handled by SIP rather 
than the build system. A SIP implementation would also go a long way to 
solving 2. It would probably also generate a C module rather than a Python 

SIP could be changed to support something like...

%ConsolidatedModule qt
%Include qtmod.sip
%Include qttable.sip

...and PyQt's configure.py would have an extra flag to specify that the 
consolidated version should be built. It's up to you whether the Qt you are 
linking against is static or dynamic.


More information about the PyQt mailing list