Skip to main content

Create QGIS projects programmatically using Python

Project description

qgis-project

qgis-project

PyPI version Python versions Tests Docs License

Create QGIS projects programmatically using Python.

This package is a thin wrapper around QGIS's most essential functions: loading layers (vector/raster, local/web), basic visualization, and basic processing.

This package is not a tool for advanced or complex visual analysis or cartographic mapping — for that, use QGIS itself or a dedicated mapping library.

from qgis_project import Project, RasterStyleBW

proj = Project()
proj.add_layer("dem.tif")                                    # raster, auto-detected
proj.add_layer("boundaries.geojson")                         # vector, auto-detected
proj.add_layer("dem.tif", style=RasterStyleBW(vmin=0, vmax=3000))  # style a path directly
proj.save("output.qgz")
proj.open()     # launch QGIS for visual inspection

Installation

qgis-project is pure Python with no runtime dependencies. The real work is done by QGIS's Python API, which is not on PyPI and must be available separately. There are two good ways to set this up — pick based on whether you already use the QGIS desktop application.

Option A — drive a local QGIS install (lightweight env)

If you have the QGIS desktop app installed, the package auto-discovers it and runs your script through QGIS's own bundled Python via its entrypoint launcher. You can then install qgis-project into any Python environment (venv, conda, system) with minimal overhead — the qgis package from conda is not required.

pip install qgis-project
# …and have a standalone QGIS desktop install on the machine (auto-discovered)
  • ✅ Tiny environment, a single QGIS install, and no QGIS/Python version conflicts.
  • ⚠️ Slightly hacky: execution runs in a separate process, so there are no live QGIS objects (e.g. no snapshot()).

Ready-made env: environments/strategy2-wrapper.yml.

Option B — install QGIS from conda-forge (in-process)

Create a conda environment that includes the qgis package; that environment's Python interpreter then runs your script directly, in-process.

conda env create -f environments/strategy3-conda.yml
conda activate qgis-project-conda

Or add QGIS to an existing environment:

conda install -c conda-forge qgis
pip install qgis-project
  • ✅ Clean, conventional, with full access to live QGIS objects.
  • ⚠️ Larger environment (the QGIS stack is >1 GB), and if you also have the desktop app you end up with multiple QGIS installs.

See How qgis-project connects to QGIS in the docs for a full explanation of every approach and how to force a specific one with QGIS_PROJECT_LAUNCH_MODE.

Usage

Basic project

from qgis_project import Project

proj = Project()
proj.add_layer("dem.tif")
proj.add_layer("roads.geojson")
proj.save("my_project.qgz")
proj.exit()

Layer groups

proj.add_layer(RasterLayer("dem.tif", group="terrain"))
proj.add_layer(RasterLayer("slope.tif", group=["terrain", "derived"]))

Raster styling

Class Effect
RasterStyleBW Grayscale with contrast stretch
RasterStyleSinglePseudocolor Single-band color ramp
RasterStyleMultiBandColor Multi-band RGB/false-color composite
from qgis_project import RasterLayer, RasterStyleBW

layer = RasterLayer(
    file="dem.tif",
    name="Elevation",
    group="terrain",
    style=RasterStyleBW(vmin=0, vmax=3000),
)
proj.add_layer(layer)

You can also pass a path and styling straight to add_layer without constructing a RasterLayer yourself — a RasterLayer is built automatically when a raster-specific keyword (a RasterStyle, band_idx, or statistics_kwargs) is given:

proj.add_layer("dem.tif", name="Elevation", group="terrain",
               style=RasterStyleBW(vmin=0, vmax=3000))

If vmin/vmax are omitted they are computed from the layer data.

RasterStyleMultiBandColor requires band_idx to be a list of three band numbers [R, G, B]:

from qgis_project import RasterStyleMultiBandColor

layer = RasterLayer(
    file="rgb.tif",
    band_idx=[1, 2, 3],
    style=RasterStyleMultiBandColor(),
)
proj.add_layer(layer)

Vector styling

Class Effect
VectorStyleSingleSymbol Uniform fill/line/marker color and outline
VectorStyleCategorized One color per unique attribute value
VectorStyleGraduated Equal-interval color classes (choropleth) for a numeric attribute
from qgis_project import Layer, VectorStyleSingleSymbol

layer = Layer(
    file="regions.geojson",
    style=VectorStyleSingleSymbol(color="red", outline_color="black", outline_width=1.0),
)
proj.add_layer(layer)

VectorStyleCategorized and VectorStyleGraduated work on point, line, and polygon layers alike:

from qgis_project import VectorStyleCategorized, VectorStyleGraduated

layer = Layer("regions.geojson", style=VectorStyleCategorized(field="class", colormap="Spectral"))
layer = Layer("regions.geojson", style=VectorStyleGraduated(field="value", num_classes=5, colormap="Viridis"))

If vmin/vmax are omitted from VectorStyleGraduated, they are computed from the field's data. outline_color/outline_width on VectorStyleSingleSymbol have no effect on line layers (a line has no separate outline). For point layers, VectorStyleSingleSymbol also accepts size (marker size in mm) and marker_shape (e.g. "circle", "square", "triangle", "star").

Filtering, labels, and scale-based visibility

Layer.filter restricts a vector layer to features matching a QGIS expression (QgsVectorLayer.setSubsetString):

layer = Layer("regions.geojson", filter="population > 1000")

Layer.labels adds attribute-based labels, independent of style:

from qgis_project import VectorLabels

layer = Layer("regions.geojson", labels=VectorLabels(field="name", size=12, color="black"))

Layer.min_scale/Layer.max_scale set scale-dependent visibility (scale denominators). min_scale is the most zoomed-out scale at which the layer is still visible; max_scale is the most zoomed-in scale at which it's still visible:

layer = Layer("regions.geojson", max_scale=50000)  # hidden once zoomed in past 1:50,000

Open in QGIS

proj.open("output.qgz")      # saves and launches QGIS
proj.print_layer_tree()      # inspect the layer tree in the terminal

Development

Install with dev dependencies:

pip install -e ".[dev]"

Run unit tests (no QGIS required):

pytest -m "not qgis"

Run integration tests (QGIS environment required):

pytest -m qgis

Run the manual visual test:

python scripts/manual_test.py

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qgis_project-1.1.0.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qgis_project-1.1.0-py3-none-any.whl (32.6 kB view details)

Uploaded Python 3

File details

Details for the file qgis_project-1.1.0.tar.gz.

File metadata

  • Download URL: qgis_project-1.1.0.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qgis_project-1.1.0.tar.gz
Algorithm Hash digest
SHA256 58c5613063bb9c375be6c437517acbcb4f29bb65da45224ab394a5e2256763f4
MD5 baa96c9c9af98e76c99c05f3dead5183
BLAKE2b-256 d598d183e8be3d413f51d3a3c69d90166eaf393397709d07e29cf389a649038b

See more details on using hashes here.

Provenance

The following attestation bundles were made for qgis_project-1.1.0.tar.gz:

Publisher: publish.yml on ColinMoldenhauer/qgis-project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file qgis_project-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: qgis_project-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 32.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qgis_project-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 710238d271f017a2b0c100d0b8453b2bd76c7c26d97f21a12d10f05553c1e62a
MD5 251ab8049e8a74aac9ff34e6d0a19a04
BLAKE2b-256 6e2b14f953ea3e2e558fd775a626e4a5d6984392a68fe2cc36206baccc12939c

See more details on using hashes here.

Provenance

The following attestation bundles were made for qgis_project-1.1.0-py3-none-any.whl:

Publisher: publish.yml on ColinMoldenhauer/qgis-project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page