[PyQt] PyQt4 for Python 3

Mark Summerfield list at qtrac.plus.com
Wed Jun 10 10:59:00 BST 2009

On 2009-06-10, Phil Thompson wrote:
> On Wed, 10 Jun 2009 07:40:52 +0100, Mark Summerfield <mark at qtrac.eu> 
> > On 2009-06-09, Phil Thompson wrote:
> >> On Sat, 6 Jun 2009 08:36:44 +0100, Mark Summerfield
> >> I can't reproduce this. Any chance you were hitting the tab order bug
> and
> >> not noticing and the .py file was truncated?
> >
> > Yes, that is exactly what happened, so presumably the fix will be in the
> > next snapshot as per your off-list email.
> Yes (ie. the current snapshot).
> > D'you know when the next actual release will be? I have converted the
> > book's examples but don't want to upload them until I can specify a
> > version of PyQt for which they'll work (i.e., one that has the tab order
> > bug fixed), and that is a proper release rather than just a snapshot.
> I plan new releases of PyQt 3, PyQt 4 and SIP this weekend. PyQt 3 and SIP
> have minor regressions (but regressions none the less). Given they need
> releases I may as well release PyQt 4 with the tab order fix for Python 3
> as well.

Well as soon as there's a PyQt4 for Python 3 I'll post the converted
examples---but not before the middle of the month now 'cos I'm too busy
next week.

> >> > (2) Behaviour change.
> >> >     QImageReader.supportedImageFormats() and
> >> >     QImageWriter.supportedImageFormats() both return a list of
> >> >     QByteArrays. With Python 2 you can convert each QByteArray to a
> >> >     unicode string like this:
> >> > 	text = unicode(byte_array)
> >> >     If you change this for Python 3 version to:
> >> > 	text = str(byte_array) # str is Unicode in Python 3
> >> >     it will "work", but the string you'll get back will be the repr,
> >> >     e.g., "PyQt4.QtCore.QByteArray(b'bmp').
> >> >     For Python 3 I'm now doing it like this:
> >> > 	text = byte_array.data().decode("ascii") # text == "bmp"
> >> >     I'm not saying this is the best way, just a way that works.
> >>
> >> Given that Python 3 wants you to be explicit about encodings then it
> >> doesn't seem unreasonable that you have to do this.
> >>
> >> Happy to debate this as it is the most difficult area of the Python 3
> >> support.
> >
> > There are very few places in the Qt API where QByteArrays are returned,
> > so I don't think it is a problem calling .data().decode("ascii") on them
> > or writing a trivial strListFromByteArray() function when they are. I
> > only mentioned it so that people are aware of the difference from how it
> > is done in Python 2.
> It would have been better if those methods returned a QString.

Sure, there are these few unfortunate places in the Qt API that return
QByteArrays---the MIME data APIs have the same problem. I think it would
be okay (and more convenient) for PyQt to return them as QStrings
though since in all the cases I can think of they're always ASCII.

> > I found the conversion of the book's examples to Python 3 pretty easy,
> > with no nasty surprises or problems, although it was a bit tedious since
> > I did them all by hand.
> >
> > Of course PyQt still has both QString and QVariant---so there is still
> > the need for annoying conversions, but at least getting rid of them is
> > on the roadmap.
> That is the subject of the next round of development - though 75% of the
> work has already been done.

I'm really looking forward to that! I think it will be a big step

Also, just realised that the roadmap doesn't mention exceptions.

I was hoping that, for example, QString.toInt() would return an int on
success and raise a ValueError (or whatever) on failure to be more
Pythonic. Similarly QFile.open().

The thing I find particularly galling about QString.toInt() returning a
tuple is that it is really easy to write:

    my_int = someQString.toInt()

and not realise until sometime later in the code that my_int is in fact
a tuple---or maybe not notice at all if you're really only checking for

    if not my_int:
	# meant for zero but actually will never get here

Still I guess the problem will go away once QString is gone, since we'll
just write:

    my_int = int(some_string)

in the normal way.

> > PS I think that QUrl is a good candidate for having __hash__.
> The problem is that (unlike the other candidates) QUrl is not
> supported by qHash() which means that I'd have to invent a hash
> function. This would then cause potential problems if QUrl support was
> added to qHash() at a later date. It would be better to persuade Nokia
> to add the support to qHash().

One way to do it is to use qHash(QUrl.toString()). Of course two QUrls
could produce different QStrings for equivalent URLs, so it would only
guarantee uniqueness of the QString representation, not URL uniqueness;
but that might be sufficient for the common cases.

Mark Summerfield, Qtrac Ltd, www.qtrac.eu
    C++, Python, Qt, PyQt - training and consultancy
        "Rapid GUI Programming with Python and Qt" - ISBN 0132354187

More information about the PyQt mailing list