Opening a vector layer under Python QGis: the worst case !🔗
Today I have been stuck by something quite strange under Python environnement of QGis. I just wanted to open an Oracle vector layer and add it to the layer registry.
Here is what I tried (you can try it in the QGis Python Console from Extensions menu):
uri = QgsDataSourceURI() uri.setConnection("","1521", "geobase", "user", "password") uri.setDataSource("SCHEMA","TABLE", v = QgsVectorLayer(uri.uri(), "MY_LAYER", "oracle") QgsMapRegistry.instance().addMapLayer(v, True)
When launching the addMapLayer method, nothing moves on QGis interface and after a bit of digging in the log messages, I found nothing suspicious…
I tried to grab the state of the layer. You can do it with the isValid method which is inherited from the QgsMapLayer class. With all of the layers I tried to open, v.isValid() always returned False.
I tried to use the error() method which returned a QgsError object to try to find why my layer was invalid. But v.error().message() was always empty.
I remembered that I've got a special layer in my Oracle database. It is the only one which is well declared in Oracle metadata table (ALL_SDO_GEOM_METADATA view). When I tried the above lines code, I was able to open the layer in QGis map dialog. This special layer just have a well declared SRID, a well declared extent and stores only one type of geometry (Polygon).
I immediately struggle in QGis Python Console to find how to force a CRS for a QgsVectorLayer. The only way I found was to use the setCrs() method directly from the QgsVectorLayer class:
uri = QgsDataSourceURI() uri.setConnection("","1521", "geobase", "user", "password") uri.setDataSource("SCHEMA","TABLE", v = QgsVectorLayer(uri.uri(), "MY_LAYER", "oracle") v.setCrs(QgsCoordinateSystem(u"EPSG:27562")
But declaring the CRS is finally not required: if there is no SRID for the layer, QGis just use the CRS of the project (it depends on what you have configured in your QGis parameters). Furthermore, adding a CRS with the above method does not change the isValid() status…
Actually, the real problem was a wkbType one. All of my unopenable layers were declared with a wkbType to WkbUnknown. After re-reading QGis API documentation, the only way I've find so far to force the wkbType of a layer is to use uri.setWkbType() method. There is no other choice.
To open a layer with multiple geometry types, you have to add a little bit of code to the above snippet:
uri = QgsDataSourceURI() uri.setConnection("","1521", "geobase", "user", "password") uri.setDataSource("SCHEMA","TABLE", uri.setWkbType(QGis.WkbPolygon) v = QgsVectorLayer(uri.uri(), "MY_LAYER", "oracle") QgsMapRegistry.instance().addMapLayer(v, True)
It took just 3 hours of work and search to find the solution. Why not make it public ?