15

I am just learning python and Qt these days. So please consider that this will be a newbie question, but I am stuck here.

import sys
from PyQt4.QtCore import *

data1 = 'string'
data2 = QVariant(data1)
data3 = data2.toPyObject()

I expected data3 is the same as data1, 'string'. However in my system data3 is

PyQt4.QtCore.QString(u'string')

It is not a big deal if the data I want to handle is simple like example, but I want to handle 'dict' type data so I need to fix this problem.

I think this is encoding problem, but can't find how to fix it.

*In every document I am declaring that:

#-*- coding: utf-8 -*-
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Jonas Hong
  • 275
  • 1
  • 2
  • 7
  • 2
    You can solve that "problem" by [setting `QString` api to 2](http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/incompatible_apis.html) but, why do you need to convert to `QVariant` and back? – Avaris Feb 13 '12 at 08:38

3 Answers3

15

You can work around this issue by wrapping your data in an immutable container:

>>> from PyQt4.QtCore import QVariant
>>> data = {'key1': 123, 'key2': 456}
>>> v = QVariant((data,))
>>> v.toPyObject()[0]
{'key2': 456, 'key1': 123}
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • how does (data,) makes data immutable, isnt just (data) behaves as an immutable or adding "," makes it a tuple ? – Ciasto piekarz Feb 13 '13 at 17:37
  • 3
    @san. It doesn't make the _data_ immutable. If the data is put inside an immutable container (such as a tuple), no attempt at conversion will be made. A tuple cannot be converted to an equivalent C++ type, so both the tuple and its contents will remain unchanged. It's also worth poiting out that there is a performance advantage from doing things this way, because it bypasses all the overhead of converting back and forth between Python and C++ types. – ekhumoro Feb 13 '13 at 18:27
0

Before you can compare data1 and data3 you need to convert the QString to Python string simply writing:

>>> same_as_data1 = str(data3)

Now you've got back the same string:

>>> data1 == data
data1 == same_as_data1
True

Wherever a string appears (as key or values) it will be mapped to QString. You can do the conversion either manually, for example:

d = QVariant({'key1':123}).toPyObject()
d_with_str_keys = dict((str(k), v) for k,v in d.iteritems())

or you can change the QString behaviour, as Avaris pointed out above.

dawe
  • 463
  • 2
  • 8
  • Thank you for your answer. Yes, it works for strings. Could you tell me how to handle 'dict' type data? `code` QVariant({'key1':123}).toPyObject() `code` is `code`{PyQt4.QtCore.QString(u'key1'): 1234}`code` and I can't transform it to original dict type data – Jonas Hong Feb 13 '12 at 08:41
-2

You can convert the dict into a string and after just eval(str) it back to a dict:

pydict  = {'key1': 'val1', 'key2': 'val2'}
variant = QtCore.QVariant( pydict )
...
pydict = eval( str( variant.toString() ) )
print pydict
>>> {'key1': 'val1', 'key2': 'val2'}

Just keep in mind the eval could fail if it's not able to convert one of the keys or values from string to dict. this can happen if you have a none built_in types (str, int, list.. ) but in your case it will work no problems.

Asi
  • 116
  • 1
  • 9