Create QGIS projects programmatically using Python
Project description
qgis-project
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
Install the package:
pip install qgis-project
QGIS is not on PyPI and must be available separately. The recommended approach is a dedicated conda environment:
conda env create -f environment_platform_independent.yml
conda activate qgis-env-pi
pip install qgis-project
Or install QGIS from conda-forge into an existing environment:
conda install -c conda-forge qgis
pip install qgis-project
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qgis_project-1.0.1.tar.gz.
File metadata
- Download URL: qgis_project-1.0.1.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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a6a976f9168092eb62959958ef45ba376e7eddba7cb818331101ec0e9e50034
|
|
| MD5 |
8fd0e323b37f9d8547bc2c90b9a48562
|
|
| BLAKE2b-256 |
3185062f1c2daa72f0b6886c538b39928170248466e0fee8531b45e389609f3e
|
Provenance
The following attestation bundles were made for qgis_project-1.0.1.tar.gz:
Publisher:
publish.yml on ColinMoldenhauer/qgis-project
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qgis_project-1.0.1.tar.gz -
Subject digest:
0a6a976f9168092eb62959958ef45ba376e7eddba7cb818331101ec0e9e50034 - Sigstore transparency entry: 2007471241
- Sigstore integration time:
-
Permalink:
ColinMoldenhauer/qgis-project@e95c00383f3f50a319284f850e3eed0e18ddf695 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/ColinMoldenhauer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e95c00383f3f50a319284f850e3eed0e18ddf695 -
Trigger Event:
push
-
Statement type:
File details
Details for the file qgis_project-1.0.1-py3-none-any.whl.
File metadata
- Download URL: qgis_project-1.0.1-py3-none-any.whl
- Upload date:
- Size: 28.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c651db6343e8a5f39435a9a646fde91ba1909bc80fc7462645de099d4ac7af4f
|
|
| MD5 |
43b47c7e27eff96164bc4bf956b8f263
|
|
| BLAKE2b-256 |
0209d7ae08a410b1045bfeef5cbb1d6a7d63c64cf8adf129dc95fb0bca8d6d7c
|
Provenance
The following attestation bundles were made for qgis_project-1.0.1-py3-none-any.whl:
Publisher:
publish.yml on ColinMoldenhauer/qgis-project
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qgis_project-1.0.1-py3-none-any.whl -
Subject digest:
c651db6343e8a5f39435a9a646fde91ba1909bc80fc7462645de099d4ac7af4f - Sigstore transparency entry: 2007471367
- Sigstore integration time:
-
Permalink:
ColinMoldenhauer/qgis-project@e95c00383f3f50a319284f850e3eed0e18ddf695 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/ColinMoldenhauer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e95c00383f3f50a319284f850e3eed0e18ddf695 -
Trigger Event:
push
-
Statement type: