QGIS 2.0: Dealing with Null values in pyqgis

Nothing in life ever comes free. Each time you make a desision there can sometimes be long a lasting effect. This is exectly the case with the new QGIS 2.0 pyqgis API. Changing to the new api was a big step in order make the API clear and more Pythonic. But there was a small detail to fix.

In QGIS 2.0 we can now just do this to read the attribute value for a field:

>>> feature['yourcolumn']
"Hello World"

What would you expect to get if the value was NULL (not empty string). Would you expect to see None? You would think so. Right? However lets just check that.

>>> feature['yourcolumn']

NULL? What the heck? That isn’t None! What is NULL?

>>> type(NULL)
<class 'PyQt4.QtCore.QPyNullVariant'>

QPyNullVariant WA! WHAAAT! Why didn’t we get None? Turns out by removing QVariant from PyQt it had some impact on methods that expected a NULL QVariant – A QVariant with no value. Passing None didn’t work because those methods needed the type information that QVariant holds, even when NULL.

When using SIP V2, which is what QGIS 2.0 is using, PyQt will auto convert any Null QVariants to QPyNullVariant.

The NULL you see is a variable masking the QPyNullVariant so that the output is nicer and it’s easier to work with. We have also added a bunch of methods to QPyNullVariant in order to make it act as much like None as we can.

If you see a NULL this is how you can deal with it:

>>> feature['yourcolumn']

>>> if not feature['nullcolumn']:
>>> print "Was null"
Was null

>>> if feature['nullcolumn'] == NULL:
>>> print "Was null"
Was null

NULL will also return False if boolean checked:

>>> value = NULL
>>> if value:
... print "This value wasn't null"
... else:
... print 'This value was null'
This value was null

It will also be equal to any other NULL aka QPyNullVariant variable

>>> value = NULL
>>> value2 = NULL
>>> value == value2
>>> value = 100
>>> value2 = NULL
>>> value == value2

Does None is NULL work? No.

One way to check if something is Null in Python is to use value is None however this will not work with our NULL type. Overloading the is operator in Python is not supported and there is no way we can support this – trust me I have tried. is is really doing id(object) == id(object) under the hood:

DO NOT do the following if you are checking for null values in pyqgis unless you know the return type is None:

>>> value = NULL
>>> value is None

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s