3

I have some problems with PyQGIS while generating a layout.

Here is a minimal (non-)working example in which I first load some layers with their styles. Then I would like to export them using a layout exporter but I only have blank files.

EDIT: simpler code

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import os

from PyQt5.QtCore import QSize
from qgis.core import *

logger = logging.getLogger(__name__)

# supply path to qgis install location
QgsApplication.setPrefixPath('/usr', True)

# create a reference to the QgsApplication, setting the
# second argument to False disables the GUI
qgs = QgsApplication([], False)

# load providers
qgs.initQgis()

# Write your code here to load some layers, use processing
# algorithms, etc.

project = QgsProject.instance()  # type:QgsProject
project.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))

dbpath = os.path.abspath(os.path.join('MWE.sqlite'))
dirpath = os.path.dirname(dbpath)

# Load cities layer
cities_style = os.path.join(dirpath, 'Style_Cities.qml')
display_name = 'Communes'
table = 'cities'
uri = dbpath + '|layername={}'.format(table)
cities = QgsVectorLayer(uri, display_name, 'ogr')
if not cities.isValid():
    msg = 'The loading of the layer named {!r} from the uri: {!r} failed.'.format(table, uri)
    logger.critical(msg)
    raise RuntimeError(msg)

# Add the layer without showing it
project.addMapLayer(cities)  # ,False)

# Style the layer
cities.loadNamedStyle(cities_style)

# Load additional layers
# ...
#

#
# Layout
#
layout = QgsPrintLayout(project)
layout.initializeDefaults()
layout.setName('console')
layout_page = QgsLayoutItemPage(layout)
layout_page.setPageSize(QgsLayoutSize(210, 297, QgsUnitTypes.LayoutMillimeters))
layout_page.decodePageOrientation('Portrait')

extent = cities.extent()  # type:QgsRectangle
extent.grow(0.1)

layout_map = QgsLayoutItemMap(layout)
layers = project.mapLayers()
layers_list = layers.values()
layout_map.setLayers(layers_list)
crs = QgsCoordinateReferenceSystem('EPSG:3857')
layout_map.setCrs(crs)

layout_map.setExtent(extent)
layout_map.refresh()
# layout.addLayoutItem(layout_map) # Cause the error on PNG export
layout.setReferenceMap(layout_map)

layout_exporter = QgsLayoutExporter(layout)
image_export_settings = QgsLayoutExporter.ImageExportSettings()
image_export_settings.dpi = 200
image_export_settings.imageSize = QSize(2000, 2000)  # pixels

res = layout_exporter.exportToImage(os.path.abspath('toto.png'), image_export_settings)
if res != QgsLayoutExporter.Success:
    raise RuntimeError()

pdf_export_settings = QgsLayoutExporter.PdfExportSettings()
pdf_export_settings.dpi = 200
res = layout_exporter.exportToPdf(os.path.abspath("toto.pdf"),     pdf_export_settings)
if res != QgsLayoutExporter.Success:
    raise RuntimeError()

# Exit
qgs.exitQgis()

I have the following error for the PNG export:

ERROR 6: The PNG driver does not support update access to existing datasets.

EDIT: if I comment the line layout.addLayoutItem(layout_map), the error disappears. It makes sense because I already provide layout to the constructor of the layout_map object. The link is already existing.

Nevertheless, I still get blank files.

EDIT: here is a link to download a valid database and style files to make the MWE work: https://we.tl/t-pwuEm8WXCd

  • Does the file get created despite this error? – ndawson Sep 11 '18 at 19:16
  • The files are created but are empty. A white PNG image and a white single page PDF are generated. – Benoît Vinot Sep 12 '18 at 8:35
  • Instead of project.addMapLayer(cities, False), try project.addMapLayer(cities) – artwork21 Sep 12 '18 at 11:47
  • @artwork21 I have tried without the "False" but I still get the same result: blank files are generated and the error above for the PNG export still exists – Benoît Vinot Sep 12 '18 at 13:23
  • Something seems off with adding the layer logic, maybe the url? After this statement addMapLayer() you should see the layer features in the map canvas. Are you able to manually add the sqlite layer using the UI and see features? If so, print off the url variable and compare that with the manual UI layer source path. – artwork21 Sep 12 '18 at 13:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.