Project URL: https://github.com/qgis/QGIS
Developer manual: https://docs.qgis.org/3.40/en/docs/pyqgis_developer_cookbook/
Python API reference: https://qgis.org/pyqgis/3.40/
License: GNU General Public License v2.0+
Overview
PyQGIS is the Python binding layer for the QGIS desktop GIS software, corresponding to the binding code under the python/ directory in the QGIS source code. It fully exposes the QGIS core C++ class libraries to Python, enabling developers to:
- In the QGIS Python Consoleinteractively operate
- Write standalone Python scripts(without launching the QGIS desktop)
- Develop QGIS pluginsto extend desktop functionality
- Invoke the Processing frameworkto execute 100+ spatial analysis algorithms
- Perform map rendering and export(PNG / PDF / SVG)
PyQGIS mainly includes the following modules:
| Module |
Description |
qgis.core |
Core classes—layers, features, geometry, coordinate systems, projects, Processing, etc. |
qgis.gui |
GUI components—map canvas, map tools, symbol selectors, etc. |
qgis.analysis |
Spatial analysis—interpolation, network analysis, raster calculation, etc. |
qgis.processing |
Processing algorithm invocation entry point (processing.run()) |
qgis.server |
QGIS Server Python plugin interface |
qgis.3d |
Classes related to 3D map views |
qgis.PyQt |
PyQt5/PyQt6 compatibility layer |
Environment Preparation
Prerequisites
- Install QGIS 3.16+ (3.40 LTR recommended)
- Python 3.9+ (QGIS bundled Python environment)
Using in the QGIS Python Console
Open the QGIS desktop → menu "Plugins → Python Console", and PyQGIS can be used directly:
# QGIS 控制台中无需初始化,直接使用
layer = iface.activeLayer()
print(layer.name(), layer.featureCount())
Standalone Script
When running Python scripts outside QGIS, the QGIS application must first be initialized:
import sys
from qgis.core import QgsApplication
# 初始化 QGIS(False 表示不使用 GUI)
qgs = QgsApplication([], False)
qgs.setPrefixPath("/usr", True) # Linux; Windows 示例:"C:/OSGeo4W/apps/qgis"
qgs.initQgis()
# ===== 在此处编写 PyQGIS 代码 =====
# 退出
qgs.exitQgis()
Using Processing in a Standalone Script
import sys
from qgis.core import QgsApplication
import processing
from processing.core.Processing import Processing
qgs = QgsApplication([], False)
qgs.setPrefixPath("/usr", True)
qgs.initQgis()
# 初始化 Processing 框架
Processing.initialize()
# 现在可以使用 processing.run()
result = processing.run("native:buffer", {
'INPUT': '/data/points.shp',
'DISTANCE': 100,
'OUTPUT': '/data/buffered.shp'
})
qgs.exitQgis()
Headless Server Environment
export QT_QPA_PLATFORM=offscreen
python3 my_pyqgis_script.py
Overview of Core Classes
Project and Application
| Class |
Module |
Purpose |
QgsApplication |
qgis.core |
QGIS application instance, initialize/exit |
QgsProject |
qgis.core |
Project management (singleton), load/save projects, manage layers |
Vector Layers and Features
| Class |
Module |
Purpose |
QgsVectorLayer |
qgis.core |
Vector layers (Shapefile, GeoJSON, PostGIS, memory, etc.) |
QgsFeature |
qgis.core |
A single feature (geometry + attributes) |
QgsField / QgsFields |
qgis.core |
Attribute field definitions and collections |
QgsFeatureRequest |
qgis.core |
Feature query filters (spatial/attribute conditions) |
QgsVectorFileWriter |
qgis.core |
Vector data output (SHP, GPKG, GeoJSON, etc.) |
QgsVectorLayerUtils |
qgis.core |
Set of utility methods for vector layers |
QgsSpatialIndex |
qgis.core |
Spatial index, speeds up spatial queries |
Raster Layers
| Class |
Module |
Purpose |
QgsRasterLayer |
qgis.core |
Raster layers (GeoTIFF, VRT, WMS, etc.) |
QgsRasterPipe |
qgis.core |
Raster rendering pipeline |
QgsRasterFileWriter |
qgis.core |
Raster data output |
Geometry
| Class |
Module |
Purpose |
QgsGeometry |
qgis.core |
Geometry object encapsulation (including spatial operation methods) |
QgsPointXY |
qgis.core |
2D point coordinates |
QgsPoint |
qgis.core |
3D point coordinates (including Z / M) |
QgsRectangle |
qgis.core |
Rectangle extent (Bounding Box) |
QgsWkbTypes |
qgis.core |
WKB geometry type enumeration |
QgsDistanceArea |
qgis.core |
Distance and area calculation (supports ellipsoid) |
Coordinate reference system and transformation
| Class |
Module |
Purpose |
QgsCoordinateReferenceSystem |
qgis.core |
Coordinate reference system (CRS) object |
QgsCoordinateTransform |
qgis.core |
Coordinate transformer |
QgsCoordinateTransformContext |
qgis.core |
Coordinate transformation context |
Expressions
| Class |
Module |
Purpose |
QgsExpression |
qgis.core |
QGIS expression parsing and evaluation |
QgsExpressionContext |
qgis.core |
Expression evaluation context |
QgsExpressionContextUtils |
qgis.core |
Utility methods for creating preset expression contexts |
Processing framework
| Class |
Module |
Purpose |
processing.run() |
qgis.processing |
Core entry point for executing Processing algorithms |
QgsProcessingFeedback |
qgis.core |
Algorithm execution feedback (progress, log) |
QgsProcessingContext |
qgis.core |
Algorithm execution context |
QgsProcessingAlgorithm |
qgis.core |
Base class for custom algorithms |
QgsProcessingParameterDefinition |
qgis.core |
Base class for algorithm parameter definitions |
Map rendering
| Class |
Module |
Purpose |
QgsMapSettings |
qgis.core |
Map rendering settings (extent, CRS, layers, size) |
QgsMapRendererSequentialJob |
qgis.core |
Sequential rendering task |
QgsMapRendererParallelJob |
qgis.core |
Parallel rendering task |
QgsLayoutExporter |
qgis.core |
Print layout export (PDF, PNG, SVG) |
QgsPrintLayout |
qgis.core |
Print layout object |
Data providers
| Provider name |
Description |
Example URI |
ogr |
OGR vector (SHP, GeoJSON, GPKG, FileGDB, etc.) |
/path/to/file.shp |
gdal |
GDAL raster (GeoTIFF, VRT, ECW, etc.) |
/path/to/dem.tif |
postgres |
PostgreSQL / PostGIS |
dbname='gis' host=localhost port=5432 table="public"."layer" (geom) |
memory |
Memory layer |
Point?crs=epsg:4326&field=id:integer&field=name:string(50) |
wms |
WMS / WMTS service |
url=https://example.com/wms&layers=dem&crs=EPSG:4326 |
wfs |
WFS service |
url=https://example.com/wfs&typename=buildings |
delimitedtext |
CSV / delimited text |
file:///path/to/data.csv?delimiter=,&xField=lon&yField=lat&crs=epsg:4326 |
spatialite |
SpatiaLite database |
dbname='/path/to/db.sqlite' table="layer" (geometry) |
virtual |
Virtual layer (SQL query) |
SQL expression |
Project management
Load and save project
from qgis.core import QgsProject
project = QgsProject.instance()
# 读取项目
project.read("/path/to/project.qgs")
# 获取所有图层
layers = project.mapLayers() # 返回 dict {layer_id: layer}
# 保存项目
project.write("/path/to/output.qgs")
Add/remove layers
from qgis.core import QgsProject, QgsVectorLayer
project = QgsProject.instance()
layer = QgsVectorLayer("/data/roads.shp", "roads", "ogr")
if layer.isValid():
project.addMapLayer(layer)
# 移除图层
project.removeMapLayer(layer.id())
Vector layer operations
Load vector layer
from qgis.core import QgsVectorLayer
# 从文件加载
layer = QgsVectorLayer("/data/buildings.shp", "buildings", "ogr")
# 从 GeoPackage 加载指定图层
layer = QgsVectorLayer("/data/data.gpkg|layername=rivers", "rivers", "ogr")
# 从 PostGIS 加载
uri = 'dbname=\'gis\' host=localhost port=5432 user=\'postgres\' table="public"."parcels" (geom)'
layer = QgsVectorLayer(uri, "parcels", "postgres")
# 内存图层
layer = QgsVectorLayer("Point?crs=epsg:4326&field=id:integer&field=name:string(50)", "temp", "memory")
# 验证
if not layer.isValid():
print("图层加载失败!")
Iterate features
for feature in layer.getFeatures():
geom = feature.geometry()
attrs = feature.attributes()
print(feature.id(), geom.asWkt(), attrs)
Query features by condition
from qgis.core import QgsFeatureRequest
# 按属性过滤
request = QgsFeatureRequest().setFilterExpression('"population" > 10000')
for feature in layer.getFeatures(request):
print(feature["name"], feature["population"])
# 按空间范围过滤
from qgis.core import QgsRectangle
rect = QgsRectangle(116.0, 39.0, 117.0, 40.0)
request = QgsFeatureRequest().setFilterRect(rect)
for feature in layer.getFeatures(request):
print(feature.id())
# 限制返回字段(提升性能)
request = QgsFeatureRequest().setSubsetOfAttributes(["name", "area"], layer.fields())
Edit features
from qgis.core import QgsFeature, QgsGeometry, QgsPointXY
# 开启编辑
layer.startEditing()
# 添加要素
feat = QgsFeature(layer.fields())
feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(116.4, 39.9)))
feat.setAttributes([1, "北京"])
layer.addFeature(feat)
# 修改已有要素属性
layer.changeAttributeValue(feature_id, field_index, new_value)
# 修改几何
layer.changeGeometry(feature_id, new_geometry)
# 删除要素
layer.deleteFeature(feature_id)
# 提交修改
layer.commitChanges()
# 或回滚
# layer.rollBack()
Create vector file
from qgis.core import (
QgsVectorFileWriter, QgsVectorLayer, QgsFeature,
QgsGeometry, QgsPointXY, QgsField, QgsFields,
QgsCoordinateReferenceSystem, QgsWkbTypes
)
from qgis.PyQt.QtCore import QVariant
# 定义字段
fields = QgsFields()
fields.append(QgsField("id", QVariant.Int))
fields.append(QgsField("name", QVariant.String))
# 创建写入器
crs = QgsCoordinateReferenceSystem("EPSG:4326")
writer = QgsVectorFileWriter(
"/data/output.shp",
"UTF-8",
fields,
QgsWkbTypes.Point,
crs,
"ESRI Shapefile"
)
# 写入要素
feat = QgsFeature()
feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(116.4, 39.9)))
feat.setAttributes([1, "北京"])
writer.addFeature(feat)
del writer # 关闭文件
Write using SaveVectorOptions (recommended)
from qgis.core import QgsVectorFileWriter
options = QgsVectorFileWriter.SaveVectorOptions()
options.driverName = "GPKG"
options.fileEncoding = "UTF-8"
error = QgsVectorFileWriter.writeAsVectorFormatV3(
layer,
"/data/output.gpkg",
QgsProject.instance().transformContext(),
options
)
Spatial index
from qgis.core import QgsSpatialIndex
# 构建索引
index = QgsSpatialIndex(layer.getFeatures())
# 最近邻查询(返回要素 ID 列表)
nearest_ids = index.nearestNeighbor(QgsPointXY(116.4, 39.9), 5)
# 矩形范围查询
ids_in_rect = index.intersects(QgsRectangle(116.0, 39.0, 117.0, 40.0))
Raster layer operations
Load raster layer
from qgis.core import QgsRasterLayer
# 从文件加载
layer = QgsRasterLayer("/data/dem.tif", "DEM")
# WMS 服务
uri = "url=https://example.com/wms&layers=elevation&crs=EPSG:4326&format=image/png"
layer = QgsRasterLayer(uri, "WMS Layer", "wms")
if not layer.isValid():
print("栅格加载失败!")
Query raster values
from qgis.core import QgsPointXY, QgsRaster
# 在指定坐标获取栅格值
point = QgsPointXY(116.4, 39.9)
result = layer.dataProvider().identify(point, QgsRaster.IdentifyFormatValue)
if result.isValid():
values = result.results() # {band_number: value}
print(values)
Raster statistics
from qgis.core import QgsRasterBandStats
stats = layer.dataProvider().bandStatistics(1, QgsRasterBandStats.All)
print(f"最小值: {stats.minimumValue}")
print(f"最大值: {stats.maximumValue}")
print(f"平均值: {stats.mean}")
print(f"标准差: {stats.stdDev}")
Geometry operations
Create geometry
from qgis.core import QgsGeometry, QgsPointXY, QgsPoint
# 点
geom_pt = QgsGeometry.fromPointXY(QgsPointXY(116.4, 39.9))
# 折线
geom_line = QgsGeometry.fromPolylineXY([
QgsPointXY(0, 0), QgsPointXY(10, 10), QgsPointXY(20, 0)
])
# 面
geom_poly = QgsGeometry.fromPolygonXY([[
QgsPointXY(0, 0), QgsPointXY(10, 0),
QgsPointXY(10, 10), QgsPointXY(0, 10),
QgsPointXY(0, 0)
]])
# 从 WKT 创建
geom = QgsGeometry.fromWkt("POINT(116.4 39.9)")
# 从 WKB 创建
geom = QgsGeometry()
geom.fromWkb(wkb_bytes)
# 从 GeoJSON 创建(通过 QgsJsonUtils)
from qgis.core import QgsJsonUtils
features = QgsJsonUtils.stringToFeatureList(geojson_string)
if features:
geom = features[0].geometry()
Format export
wkt = geom.asWkt() # WKT 字符串
wkb = geom.asWkb() # WKB bytes
json_str = geom.asJson() # GeoJSON 字符串
Spatial operations
# 缓冲区
buffered = geom.buffer(100, 16)
# 交集
intersection = geom1.intersection(geom2)
# 合并
union = geom1.combine(geom2)
# 差集
difference = geom1.difference(geom2)
# 对称差
sym_diff = geom1.symDifference(geom2)
# 凸包
hull = geom.convexHull()
# 质心
centroid = geom.centroid()
# 包围盒
bbox = geom.boundingBox() # 返回 QgsRectangle
# 简化
simplified = geom.simplify(tolerance)
# 有效性检查
is_valid = geom.isGeosValid()
Spatial relationship determination
geom1.intersects(geom2) # 是否相交
geom1.contains(geom2) # 是否包含
geom1.within(geom2) # 是否在内部
geom1.overlaps(geom2) # 是否重叠
geom1.touches(geom2) # 是否相切
geom1.crosses(geom2) # 是否交叉
geom1.disjoint(geom2) # 是否不相交
geom1.equals(geom2) # 是否相等
Distance and area calculation
# 平面距离
dist = geom1.distance(geom2)
# 椭球面距离和面积(精确计算)
from qgis.core import QgsDistanceArea, QgsCoordinateReferenceSystem
da = QgsDistanceArea()
da.setSourceCrs(QgsCoordinateReferenceSystem("EPSG:4326"),
QgsProject.instance().transformContext())
da.setEllipsoid("WGS84")
length = da.measureLength(line_geom)
area = da.measureArea(polygon_geom)
# 两点间大地测量距离
d = da.measureLine(QgsPointXY(116.4, 39.9), QgsPointXY(121.5, 31.2))
Coordinate reference system and transformation
Create CRS
from qgis.core import QgsCoordinateReferenceSystem
# 从 EPSG 代码
crs = QgsCoordinateReferenceSystem("EPSG:4326")
# 从 WKT
crs = QgsCoordinateReferenceSystem.fromWkt(wkt_string)
# 从 Proj 字符串
crs = QgsCoordinateReferenceSystem.fromProj4(proj4_string)
# 获取图层 CRS
crs = layer.crs()
print(crs.authid()) # "EPSG:4326"
print(crs.description()) # "WGS 84"
Coordinate transformation
from qgis.core import QgsCoordinateTransform, QgsCoordinateReferenceSystem, QgsProject
src_crs = QgsCoordinateReferenceSystem("EPSG:4326")
dst_crs = QgsCoordinateReferenceSystem("EPSG:3857")
transform = QgsCoordinateTransform(src_crs, dst_crs, QgsProject.instance())
# 变换单个点
point = transform.transform(QgsPointXY(116.4, 39.9))
# 变换几何
geom.transform(transform)
# 反向变换
point_back = transform.transform(point, QgsCoordinateTransform.ReverseTransform)
Expressions
Basic expression evaluation
from qgis.core import QgsExpression, QgsExpressionContext, QgsExpressionContextUtils
# 简单计算
exp = QgsExpression("1 + 2 * 3")
result = exp.evaluate() # 7
# 基于要素的表达式
exp = QgsExpression('"population" / "area"')
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(layer))
for feature in layer.getFeatures():
context.setFeature(feature)
value = exp.evaluate(context)
print(feature["name"], value)
Filter features
# 表达式过滤
exp = QgsExpression('"type" = \'residential\' AND "area" > 1000')
request = QgsFeatureRequest(exp)
for feature in layer.getFeatures(request):
print(feature.attributes())
Field calculator
from qgis.core import QgsExpression
layer.startEditing()
# 使用表达式批量更新字段
expression = QgsExpression('"length" * "width"')
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(layer))
field_index = layer.fields().indexOf("area")
for feature in layer.getFeatures():
context.setFeature(feature)
value = expression.evaluate(context)
layer.changeAttributeValue(feature.id(), field_index, value)
layer.commitChanges()
Processing algorithm invocation
Basic invocation
import processing
# 运行缓冲区分析
result = processing.run("native:buffer", {
'INPUT': '/data/roads.shp',
'DISTANCE': 50,
'SEGMENTS': 10,
'END_CAP_STYLE': 0, # 0=圆形, 1=平头, 2=方形
'JOIN_STYLE': 0, # 0=圆形, 1=斜角, 2=斜切
'MITER_LIMIT': 2,
'DISSOLVE': False,
'OUTPUT': '/data/roads_buffer.shp'
})
print(result['OUTPUT']) # 输出文件路径
With feedback object
from qgis.core import QgsProcessingFeedback
feedback = QgsProcessingFeedback()
result = processing.run("native:dissolve", {
'INPUT': '/data/polygons.shp',
'FIELD': ['type'],
'OUTPUT': '/data/dissolved.gpkg'
}, feedback=feedback)
Using memory output
# OUTPUT 设为 'memory:' 前缀可得到内存图层
result = processing.run("native:buffer", {
'INPUT': layer,
'DISTANCE': 100,
'OUTPUT': 'memory:buffered'
})
buffered_layer = result['OUTPUT'] # QgsVectorLayer(内存)
Layer object as input
# 可以直接传入 QgsVectorLayer / QgsRasterLayer 对象
result = processing.run("native:clip", {
'INPUT': input_layer, # QgsVectorLayer 对象
'OVERLAY': clip_layer, # QgsVectorLayer 对象
'OUTPUT': 'memory:clipped'
})
Common Processing Algorithms
| Algorithm ID |
Description |
Key Parameters |
native:buffer |
Buffer |
INPUT, DISTANCE, SEGMENTS, DISSOLVE |
native:clip |
Vector Clip |
INPUT, OVERLAY |
native:dissolve |
Dissolve |
INPUT, FIELD |
native:intersection |
Intersection |
INPUT, OVERLAY |
native:union |
Union |
INPUT, OVERLAY |
native:difference |
Difference |
INPUT, OVERLAY |
native:centroids |
Centroid |
INPUT |
native:reprojectlayer |
Reproject |
INPUT, TARGET_CRS |
native:mergevectorlayers |
Merge Layers |
LAYERS |
native:fixgeometries |
Fix Geometries |
INPUT |
native:extractbyattribute |
Extract by Attribute |
INPUT, FIELD, OPERATOR, VALUE |
native:extractbylocation |
Extract by Location |
INPUT, INTERSECT, PREDICATE |
native:joinattributesbylocation |
Spatial Join |
INPUT, JOIN, PREDICATE, METHOD |
native:fieldcalculator |
Field Calculator |
INPUT, FIELD_NAME, FORMULA |
gdal:cliprasterbyextent |
Clip Raster by Extent |
INPUT, EXTENT |
gdal:cliprasterbymask |
Clip Raster by Mask |
INPUT, MASK |
gdal:warpreproject |
Raster Reproject |
INPUT, TARGET_CRS |
gdal:merge |
Raster Merge |
INPUT |
gdal:contour |
Contour Extraction |
INPUT, INTERVAL |
gdal:polygonize |
Raster to Vector |
INPUT |
gdal:rasterize |
Vector to Raster |
INPUT, FIELD |
Query Available Algorithms
# 在 QGIS 控制台中列出所有算法
for alg in QgsApplication.processingRegistry().algorithms():
print(alg.id(), "-", alg.displayName())
# 搜索算法
for alg in QgsApplication.processingRegistry().algorithms():
if 'buffer' in alg.id().lower():
print(alg.id(), alg.displayName())
Map Rendering and Export
Render as Image
from qgis.core import QgsMapSettings, QgsMapRendererSequentialJob
from qgis.PyQt.QtCore import QSize
settings = QgsMapSettings()
settings.setLayers([layer])
settings.setDestinationCrs(layer.crs())
settings.setExtent(layer.extent())
settings.setOutputSize(QSize(1920, 1080))
job = QgsMapRendererSequentialJob(settings)
job.start()
job.waitForFinished()
image = job.renderedImage()
image.save("/data/map_output.png")
Export PDF Using Print Layout
from qgis.core import (
QgsProject, QgsPrintLayout, QgsLayoutItemMap,
QgsLayoutExporter, QgsLayoutSize, QgsUnitTypes
)
project = QgsProject.instance()
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# 添加地图项
map_item = QgsLayoutItemMap(layout)
map_item.setRect(20, 20, 200, 150)
map_item.setExtent(layer.extent())
map_item.setLayers([layer])
layout.addLayoutItem(map_item)
# 导出 PDF
exporter = QgsLayoutExporter(layout)
pdf_settings = QgsLayoutExporter.PdfExportSettings()
exporter.exportToPdf("/data/output.pdf", pdf_settings)
Typical Workflow Examples
Example 1: Vector Format Conversion (SHP → GeoPackage)
from qgis.core import QgsVectorLayer, QgsVectorFileWriter, QgsProject
layer = QgsVectorLayer("/data/input.shp", "input", "ogr")
options = QgsVectorFileWriter.SaveVectorOptions()
options.driverName = "GPKG"
options.fileEncoding = "UTF-8"
QgsVectorFileWriter.writeAsVectorFormatV3(
layer,
"/data/output.gpkg",
QgsProject.instance().transformContext(),
options
)
Example 2: Batch Buffer + Dissolve
import processing
# 缓冲区
result1 = processing.run("native:buffer", {
'INPUT': '/data/points.shp',
'DISTANCE': 500,
'SEGMENTS': 16,
'OUTPUT': 'memory:buffered'
})
# 融合
result2 = processing.run("native:dissolve", {
'INPUT': result1['OUTPUT'],
'OUTPUT': '/data/dissolved.gpkg'
})
Example 3: Coordinate System Transformation + Attribute Filtering
import processing
# 重投影到 CGCS2000
result1 = processing.run("native:reprojectlayer", {
'INPUT': '/data/input_wgs84.shp',
'TARGET_CRS': 'EPSG:4490',
'OUTPUT': 'memory:reprojected'
})
# 按属性提取
result2 = processing.run("native:extractbyattribute", {
'INPUT': result1['OUTPUT'],
'FIELD': 'type',
'OPERATOR': 0, # 0=等于
'VALUE': 'road',
'OUTPUT': '/data/roads_cgcs2000.gpkg'
})
Example 4: Raster Clip + Slope Analysis
import processing
# 按掩膜裁剪 DEM(栅格算法使用 TEMPORARY_OUTPUT 生成临时文件)
result1 = processing.run("gdal:cliprasterbymask", {
'INPUT': '/data/dem.tif',
'MASK': '/data/boundary.shp',
'OUTPUT': 'TEMPORARY_OUTPUT' # 栅格输出不支持 memory:,使用 TEMPORARY_OUTPUT 创建临时文件
})
# 坡度分析
result2 = processing.run("gdal:slope", {
'INPUT': result1['OUTPUT'],
'OUTPUT': '/data/slope.tif'
})
Example 5: Create Vector Layer from CSV and Export
from qgis.core import QgsVectorLayer, QgsVectorFileWriter, QgsProject
# 从 CSV 加载(指定经纬度字段)
uri = "file:///data/stations.csv?delimiter=,&xField=longitude&yField=latitude&crs=epsg:4326"
layer = QgsVectorLayer(uri, "stations", "delimitedtext")
if layer.isValid():
options = QgsVectorFileWriter.SaveVectorOptions()
options.driverName = "GeoJSON"
QgsVectorFileWriter.writeAsVectorFormatV3(
layer,
"/data/stations.geojson",
QgsProject.instance().transformContext(),
options
)
Example 6: Complete Standalone Script Example
"""独立 PyQGIS 脚本:加载 SHP、缓冲区分析、导出 GeoJSON"""
import sys
from qgis.core import (
QgsApplication, QgsVectorLayer, QgsProject
)
import processing
from processing.core.Processing import Processing
# 初始化
qgs = QgsApplication([], False)
qgs.setPrefixPath("/usr", True)
qgs.initQgis()
Processing.initialize()
# 加载数据
layer = QgsVectorLayer("/data/buildings.shp", "buildings", "ogr")
assert layer.isValid(), "图层加载失败"
# 缓冲区分析
result = processing.run("native:buffer", {
'INPUT': layer,
'DISTANCE': 200,
'OUTPUT': '/data/buildings_buffer.geojson'
})
print(f"输出文件: {result['OUTPUT']}")
# 退出
qgs.exitQgis()
AI Usage Recommendations
Recommended Workflow
- Initialize Environment: Standalone scripts require
QgsApplication initialization; available directly in the QGIS console
- Load Data: Use
QgsVectorLayer / QgsRasterLayer to load data sources
- Perform Analysis: Prefer using
processing.run() to call algorithms (unified parameters, rich algorithms); use QgsGeometry methods for fine-grained operations
- Export Results: Use
QgsVectorFileWriter to write vectors,QgsRasterFileWriter to write rasters
- Cleanup and Exit: Standalone scripts call
qgs.exitQgis()
Key Considerations
- Always Check Layer Validity: After loading a layer, you must check
layer.isValid(); if invalid, check the path and Provider.
- Coordinate System Consistency: Before spatial operations, ensure all layers use the same CRS; use
native:reprojectlayer or QgsCoordinateTransform for transformation.
- Edit Mode: Modifying layer data requires
startEditing() → operation → commitChanges(); if it fails, you can rollBack()。
- Processing Memory Output: Setting OUTPUT to
'memory:name' yields an in-memory layer, avoiding the creation of temporary files.
- Ellipsoidal Calculation: When calculating distance/area for geographic coordinates (latitude/longitude), use
QgsDistanceArea and set the ellipsoid, or use a Processing algorithm to specify the ellipsoid.
- Headless Environment: On a server without a display, you must set
QT_QPA_PLATFORM=offscreen。
- Use Absolute Paths for File Paths: Avoid file-not-found issues caused by an uncertain working directory.
- Optimization for Large Data Volumes: Use
QgsSpatialIndex to accelerate spatial queries; use QgsFeatureRequest Restrict returned fields and range.
- Expression syntax: field names use double quotes
"field", string values use single quotes 'value'。
- QGIS version compatibility: Some APIs change between versions; it is recommended to use 3.40 LTR to get a stable interface.
Error handling
# 图层加载失败
layer = QgsVectorLayer(path, name, provider)
if not layer.isValid():
print(f"图层加载失败: {layer.error().message()}")
# Processing 算法错误
try:
result = processing.run("native:buffer", params, feedback=feedback)
except Exception as e:
print(f"算法执行失败: {e}")
# 编辑提交失败
if not layer.commitChanges():
errors = layer.commitErrors()
print(f"提交失败: {errors}")
layer.rollBack()
Reference links