[{"data":1,"prerenderedAt":2332},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script":3},{"id":4,"title":5,"body":6,"description":2320,"extension":2321,"meta":2322,"navigation":449,"path":2328,"seo":2329,"stem":2330,"__hash__":2331},"docs\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script\u002Findex.md","Run a Processing Algorithm from a Script in PyQGIS",{"type":7,"value":8,"toc":2305},"minimark",[9,13,34,58,65,349,354,375,387,391,409,583,633,637,644,670,701,705,715,868,889,892,949,974,978,984,1243,1258,1261,1339,1342,1346,1352,1685,1705,1709,1719,1919,1941,1945,1951,2024,2029,2033,2040,2100,2114,2118,2175,2179,2203,2207,2221,2234,2257,2266,2270,2301],[10,11,5],"h1",{"id":12},"run-a-processing-algorithm-from-a-script-in-pyqgis",[14,15,16],"p",{},[17,18,19,24,25,24,29,33],"em",{},[20,21,23],"a",{"href":22},"\u002F","Home"," → ",[20,26,28],{"href":27},"\u002Fspatial-data-processing-automation\u002F","Spatial Data Processing & Automation",[20,30,32],{"href":31},"\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002F","Batch Processing with PyQGIS"," → Run a Processing Algorithm from a Script",[14,35,36,37,41,42,46,47,50,51,54,55,57],{},"Inside the QGIS Python Console, ",[38,39,40],"code",{},"processing.run(...)"," just works because the application and the Processing framework are already initialized for you. In a ",[43,44,45],"strong",{},"standalone"," script — one launched from your terminal, a cron job, or a CI pipeline without the QGIS GUI — none of that setup exists yet. You have to start ",[38,48,49],{},"QgsApplication",", initialize the Processing framework, and register the native algorithm provider before any ",[38,52,53],{},"processing.run"," call will succeed. This is the foundation of headless ",[20,56,32],{"href":31},", the parent guide this recipe sits under.",[14,59,60,61,64],{},"This page covers the exact bootstrap sequence, how to discover an algorithm's parameter names with ",[38,62,63],{},"processing.algorithmHelp",", how to run an algorithm, and how to read its output dictionary — then how to shut down cleanly.",[66,67,72,73,72,77,72,81,72,88,72,97,72,103,72,113,72,72,119,72,127,72,133,72,138,72,142,72,72,147,72,150,72,153,72,156,72,160,72,72,163,72,166,72,169,72,172,72,176,72,72,179,72,182,72,185,72,188,72,192,72,72,195,72,198,72,201,72,204,72,208,72,212,72,219,72,223,72,227,72,72,231,72,237,72,72,243,72,252,72,257,72,262,72,72,267,72,274,72,281,72,287,72,290,72,72,295,72,300,72,306,72,310,72,72,314,72,317,72,321,72,324],"svg",{"viewBox":68,"role":69,"ariaLabel":70,"xmlns":71},"0 0 800 362","img","Flow diagram of the standalone PyQGIS bootstrap, run, and shutdown sequence, showing that the QGIS Console skips the bootstrap steps","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[74,75,76],"title",{},"Standalone bootstrap versus the QGIS Console entry point",[78,79,80],"desc",{},"A standalone script must run five bootstrap steps — create a headless QgsApplication, setPrefixPath plus initQgis, add the plugins path, Processing.initialize, and addProvider(QgsNativeAlgorithms) — before it can call processing.run, read result OUTPUT, and exitQgis. The QGIS Console skips the whole bootstrap block and enters directly at processing.run.",[82,83],"rect",{"x":84,"y":84,"width":85,"height":86,"fill":87},"0","800","362","#f6f3ea",[89,90,96],"text",{"x":91,"y":92,"fill":93,"style":94,"textAnchor":95},"400","28","#17211d","text-anchor:middle;font-family:sans-serif;font-size:16px;font-weight:bold","middle","Standalone bootstrap → run → shutdown",[89,98,102],{"x":91,"y":99,"fill":100,"style":101,"textAnchor":95},"48","#2f3b35","text-anchor:middle;font-family:sans-serif;font-size:12px","A standalone script must set up everything the QGIS Console has already done for you",[82,104],{"x":105,"y":106,"width":107,"height":108,"rx":109,"fill":110,"stroke":111,"style":112},"24","66","752","130","10","#fffdf7","#0f766e","stroke-width:2;stroke-dasharray:6 4",[89,114,118],{"x":115,"y":116,"fill":111,"style":117},"40","88","font-family:sans-serif;font-size:12px;font-weight:bold","BOOTSTRAP — standalone script only",[82,120],{"x":121,"y":122,"width":108,"height":123,"rx":124,"fill":110,"stroke":125,"style":126},"36","102","76","6","#2563eb","stroke-width:2",[128,129],"circle",{"cx":130,"cy":131,"r":132,"fill":125},"51","119","9",[89,134,137],{"x":130,"y":135,"fill":110,"style":136,"textAnchor":95},"123","text-anchor:middle;font-family:sans-serif;font-size:11px;font-weight:bold","1",[89,139,49],{"x":140,"y":141,"fill":93,"style":136,"textAnchor":95},"101","150",[89,143,146],{"x":140,"y":144,"fill":100,"style":145,"textAnchor":95},"166","text-anchor:middle;font-family:monospace;font-size:10px","([], False)",[82,148],{"x":149,"y":122,"width":108,"height":123,"rx":124,"fill":110,"stroke":125,"style":126},"182",[128,151],{"cx":152,"cy":131,"r":132,"fill":125},"197",[89,154,155],{"x":152,"y":135,"fill":110,"style":136,"textAnchor":95},"2",[89,157,159],{"x":158,"y":141,"fill":93,"style":136,"textAnchor":95},"247","setPrefixPath",[89,161,162],{"x":158,"y":144,"fill":100,"style":145,"textAnchor":95},"+ initQgis()",[82,164],{"x":165,"y":122,"width":108,"height":123,"rx":124,"fill":110,"stroke":125,"style":126},"328",[128,167],{"cx":168,"cy":131,"r":132,"fill":125},"343",[89,170,171],{"x":168,"y":135,"fill":110,"style":136,"textAnchor":95},"3",[89,173,175],{"x":174,"y":141,"fill":93,"style":136,"textAnchor":95},"393","sys.path +=",[89,177,178],{"x":174,"y":144,"fill":100,"style":145,"textAnchor":95},"plugins dir",[82,180],{"x":181,"y":122,"width":108,"height":123,"rx":124,"fill":110,"stroke":125,"style":126},"474",[128,183],{"cx":184,"cy":131,"r":132,"fill":125},"489",[89,186,187],{"x":184,"y":135,"fill":110,"style":136,"textAnchor":95},"4",[89,189,191],{"x":190,"y":141,"fill":93,"style":136,"textAnchor":95},"539","Processing",[89,193,194],{"x":190,"y":144,"fill":100,"style":145,"textAnchor":95},".initialize()",[82,196],{"x":197,"y":122,"width":108,"height":123,"rx":124,"fill":110,"stroke":125,"style":126},"620",[128,199],{"cx":200,"cy":131,"r":132,"fill":125},"635",[89,202,203],{"x":200,"y":135,"fill":110,"style":136,"textAnchor":95},"5",[89,205,207],{"x":206,"y":141,"fill":93,"style":136,"textAnchor":95},"685","addProvider",[89,209,211],{"x":206,"y":144,"fill":100,"style":210,"textAnchor":95},"text-anchor:middle;font-family:monospace;font-size:9px","QgsNativeAlgorithms()",[213,214],"line",{"x1":215,"y1":216,"x2":217,"y2":216,"stroke":100,"style":218},"168","140","178","stroke-width:2;marker-end:url(#ar)",[213,220],{"x1":221,"y1":216,"x2":222,"y2":216,"stroke":100,"style":218},"314","324",[213,224],{"x1":225,"y1":216,"x2":226,"y2":216,"stroke":100,"style":218},"460","470",[213,228],{"x1":229,"y1":216,"x2":230,"y2":216,"stroke":100,"style":218},"606","616",[232,233],"polyline",{"points":234,"fill":235,"stroke":111,"style":236},"685,178 685,214 277,214 277,246","none","stroke-width:2;marker-end:url(#art)",[89,238,242],{"x":239,"y":240,"fill":111,"style":241,"textAnchor":95},"481","209","text-anchor:middle;font-family:sans-serif;font-size:11px","standalone path: all five steps first",[82,244],{"x":245,"y":246,"width":247,"height":248,"rx":249,"fill":110,"stroke":250,"style":251},"30","262","122","56","8","#15803d","stroke-width:2;stroke-dasharray:5 3",[89,253,256],{"x":254,"y":255,"fill":250,"style":136,"textAnchor":95},"91","286","QGIS Console",[89,258,261],{"x":254,"y":259,"fill":100,"style":260,"textAnchor":95},"302","text-anchor:middle;font-family:sans-serif;font-size:10px","skips bootstrap",[213,263],{"x1":264,"y1":265,"x2":144,"y2":265,"stroke":250,"style":266},"152","290","stroke-width:2;marker-end:url(#arg)",[82,268],{"x":215,"y":269,"width":270,"height":271,"rx":124,"fill":272,"stroke":250,"style":273},"250","216","82","#26322d","stroke-width:2.5",[89,275,280],{"x":276,"y":277,"fill":278,"style":279,"textAnchor":95},"276","278","#d9f99d","text-anchor:middle;font-family:monospace;font-size:11px;font-weight:bold","processing.run(",[89,282,286],{"x":276,"y":283,"fill":284,"style":285,"textAnchor":95},"296","#eaf6e3","text-anchor:middle;font-family:monospace;font-size:11px","\"native:buffer\",",[89,288,289],{"x":276,"y":221,"fill":284,"style":285,"textAnchor":95},"params)",[213,291],{"x1":292,"y1":293,"x2":294,"y2":293,"stroke":100,"style":218},"384","291","402",[82,296],{"x":297,"y":269,"width":298,"height":271,"rx":124,"fill":110,"stroke":299,"style":273},"404","176","#b45309",[89,301,305],{"x":302,"y":303,"fill":93,"style":304,"textAnchor":95},"492","284","text-anchor:middle;font-family:monospace;font-size:12px;font-weight:bold","result[\"OUTPUT\"]",[89,307,309],{"x":302,"y":308,"fill":299,"style":241,"textAnchor":95},"304","→ path or layer",[213,311],{"x1":312,"y1":293,"x2":313,"y2":293,"stroke":100,"style":218},"580","598",[82,315],{"x":316,"y":269,"width":298,"height":271,"rx":124,"fill":110,"stroke":111,"style":273},"600",[89,318,320],{"x":319,"y":303,"fill":93,"style":304,"textAnchor":95},"688","exitQgis()",[89,322,323],{"x":319,"y":308,"fill":111,"style":241,"textAnchor":95},"release + flush",[325,326,327,328,327,339,327,344,72],"defs",{},"\n    ",[329,330,334,335,327],"marker",{"id":331,"markerWidth":132,"markerHeight":132,"refX":332,"refY":187,"orient":333},"ar","7","auto","\n      ",[336,337],"path",{"d":338,"fill":100},"M0,0 L8,4 L0,8 Z",[329,340,334,342,327],{"id":341,"markerWidth":132,"markerHeight":132,"refX":332,"refY":187,"orient":333},"art",[336,343],{"d":338,"fill":111},[329,345,334,347,327],{"id":346,"markerWidth":132,"markerHeight":132,"refX":332,"refY":187,"orient":333},"arg",[336,348],{"d":338,"fill":250},[350,351,353],"h2",{"id":352},"prerequisites","Prerequisites",[355,356,357,361,372],"ul",{},[358,359,360],"li",{},"QGIS 3.34 LTR installed (bundled Python 3.12).",[358,362,363,364,367,368,371],{},"A terminal that can find the QGIS Python and libraries (use the ",[43,365,366],{},"OSGeo4W Shell"," on Windows, or ",[38,369,370],{},"python3"," from the QGIS install on Linux\u002FmacOS).",[358,373,374],{},"A test input layer to run an algorithm against.",[14,376,377,378,381,382,386],{},"Run standalone scripts with the QGIS-aware Python, not your system Python, or the ",[38,379,380],{},"qgis.core"," import will fail. For environment setup details see ",[20,383,385],{"href":384},"\u002Fpyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002Frunning-python-scripts-outside-qgis-desktop\u002F","Running Python Scripts Outside QGIS Desktop",".",[350,388,390],{"id":389},"initialize-qgsapplication-and-processing","Initialize QgsApplication and Processing",[14,392,393,394,396,397,400,401,404,405,408],{},"The bootstrap has four parts: create a headless ",[38,395,49],{},", call ",[38,398,399],{},"initQgis()",", initialize the Processing plugin, and add ",[38,402,403],{},"QgsNativeAlgorithms"," to the registry so the ",[38,406,407],{},"native:"," algorithms become available.",[410,411,416],"pre",{"className":412,"code":413,"language":414,"meta":415,"style":415},"language-python shiki shiki-themes github-dark","import sys\nfrom qgis.core import QgsApplication\n\n# 1. Headless application (second arg False = no GUI)\nqgs = QgsApplication([], False)\n\n# 2. Point at the install prefix; \"\" lets QGIS auto-detect on most setups\nQgsApplication.setPrefixPath(\"\u002Fusr\", True)\nqgs.initQgis()\n\n# 3. Initialize the Processing framework\nsys.path.append(\"\u002Fusr\u002Fshare\u002Fqgis\u002Fpython\u002Fplugins\")\nfrom processing.core.Processing import Processing\nProcessing.initialize()\n\n# 4. Register the native (C++) algorithm provider\nfrom qgis.analysis import QgsNativeAlgorithms\nQgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())\n","python","",[38,417,418,430,444,451,458,477,482,488,506,512,517,523,534,547,553,558,564,577],{"__ignoreMap":415},[419,420,422,426],"span",{"class":213,"line":421},1,[419,423,425],{"class":424},"snl16","import",[419,427,429],{"class":428},"s95oV"," sys\n",[419,431,433,436,439,441],{"class":213,"line":432},2,[419,434,435],{"class":424},"from",[419,437,438],{"class":428}," qgis.core ",[419,440,425],{"class":424},[419,442,443],{"class":428}," QgsApplication\n",[419,445,447],{"class":213,"line":446},3,[419,448,450],{"emptyLinePlaceholder":449},true,"\n",[419,452,454],{"class":213,"line":453},4,[419,455,457],{"class":456},"sjoCn","# 1. Headless application (second arg False = no GUI)\n",[419,459,461,464,467,470,474],{"class":213,"line":460},5,[419,462,463],{"class":428},"qgs ",[419,465,466],{"class":424},"=",[419,468,469],{"class":428}," QgsApplication([], ",[419,471,473],{"class":472},"sDLfK","False",[419,475,476],{"class":428},")\n",[419,478,480],{"class":213,"line":479},6,[419,481,450],{"emptyLinePlaceholder":449},[419,483,485],{"class":213,"line":484},7,[419,486,487],{"class":456},"# 2. Point at the install prefix; \"\" lets QGIS auto-detect on most setups\n",[419,489,491,494,498,501,504],{"class":213,"line":490},8,[419,492,493],{"class":428},"QgsApplication.setPrefixPath(",[419,495,497],{"class":496},"sU2Wk","\"\u002Fusr\"",[419,499,500],{"class":428},", ",[419,502,503],{"class":472},"True",[419,505,476],{"class":428},[419,507,509],{"class":213,"line":508},9,[419,510,511],{"class":428},"qgs.initQgis()\n",[419,513,515],{"class":213,"line":514},10,[419,516,450],{"emptyLinePlaceholder":449},[419,518,520],{"class":213,"line":519},11,[419,521,522],{"class":456},"# 3. Initialize the Processing framework\n",[419,524,526,529,532],{"class":213,"line":525},12,[419,527,528],{"class":428},"sys.path.append(",[419,530,531],{"class":496},"\"\u002Fusr\u002Fshare\u002Fqgis\u002Fpython\u002Fplugins\"",[419,533,476],{"class":428},[419,535,537,539,542,544],{"class":213,"line":536},13,[419,538,435],{"class":424},[419,540,541],{"class":428}," processing.core.Processing ",[419,543,425],{"class":424},[419,545,546],{"class":428}," Processing\n",[419,548,550],{"class":213,"line":549},14,[419,551,552],{"class":428},"Processing.initialize()\n",[419,554,556],{"class":213,"line":555},15,[419,557,450],{"emptyLinePlaceholder":449},[419,559,561],{"class":213,"line":560},16,[419,562,563],{"class":456},"# 4. Register the native (C++) algorithm provider\n",[419,565,567,569,572,574],{"class":213,"line":566},17,[419,568,435],{"class":424},[419,570,571],{"class":428}," qgis.analysis ",[419,573,425],{"class":424},[419,575,576],{"class":428}," QgsNativeAlgorithms\n",[419,578,580],{"class":213,"line":579},18,[419,581,582],{"class":428},"QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())\n",[14,584,585,588,589,592,593,595,596,599,600,603,604,607,608,611,612,614,615,618,619,622,623,625,626,628,629,632],{},[43,586,587],{},"Breakdown:"," ",[38,590,591],{},"QgsApplication([], False)"," starts QGIS without a GUI event loop. ",[38,594,159],{}," tells QGIS where its resources live — ",[38,597,598],{},"\u002Fusr"," is typical on Debian\u002FUbuntu; on Windows it is your OSGeo4W ",[38,601,602],{},"apps\u002Fqgis"," (or ",[38,605,606],{},"qgis-ltr",") folder. The plugins directory must be on ",[38,609,610],{},"sys.path"," before importing ",[38,613,191],{},". ",[38,616,617],{},"Processing.initialize()"," loads the GDAL\u002FSAGA\u002FGRASS providers, and ",[38,620,621],{},"addProvider(QgsNativeAlgorithms())"," adds the ",[38,624,407],{}," set that ",[38,627,617],{}," does not register on its own — skip this step and ",[38,630,631],{},"native:buffer"," and friends will be reported as unknown.",[350,634,636],{"id":635},"discover-an-algorithms-parameters","Discover an Algorithm's Parameters",[14,638,639,640,643],{},"You should never guess parameter names. ",[38,641,642],{},"processing.algorithmHelp(\"provider:name\")"," prints the full signature: every input, its type, acceptable values, and the output names.",[410,645,647],{"className":412,"code":646,"language":414,"meta":415,"style":415},"import processing\n\nprocessing.algorithmHelp(\"native:buffer\")\n",[38,648,649,656,660],{"__ignoreMap":415},[419,650,651,653],{"class":213,"line":421},[419,652,425],{"class":424},[419,654,655],{"class":428}," processing\n",[419,657,658],{"class":213,"line":432},[419,659,450],{"emptyLinePlaceholder":449},[419,661,662,665,668],{"class":213,"line":446},[419,663,664],{"class":428},"processing.algorithmHelp(",[419,666,667],{"class":496},"\"native:buffer\"",[419,669,476],{"class":428},[14,671,672,674,675,500,678,500,681,500,684,500,687,690,691,693,694,697,698,386],{},[43,673,587],{}," This prints each parameter with its internal key (e.g. ",[38,676,677],{},"INPUT",[38,679,680],{},"DISTANCE",[38,682,683],{},"SEGMENTS",[38,685,686],{},"DISSOLVE",[38,688,689],{},"OUTPUT",") and the expected value type. Those keys are exactly what you put in the parameters dictionary for ",[38,692,53],{},". To list every available algorithm ID instead, iterate ",[38,695,696],{},"QgsApplication.processingRegistry().algorithms()"," and print each ",[38,699,700],{},"alg.id()",[350,702,704],{"id":703},"run-the-algorithm-and-read-output","Run the Algorithm and Read OUTPUT",[14,706,707,708,711,712,714],{},"With parameters known, call ",[38,709,710],{},"processing.run(algorithm_id, params)",". It returns a dictionary; the geometry\u002Ffile result is almost always under the ",[38,713,689],{}," key.",[410,716,718],{"className":412,"code":717,"language":414,"meta":415,"style":415},"import processing\n\nparams = {\n    \"INPUT\": \"\u002Fdata\u002Fpoints.gpkg\",\n    \"DISTANCE\": 250,            # in the layer's CRS units\n    \"SEGMENTS\": 8,\n    \"DISSOLVE\": False,\n    \"OUTPUT\": \"\u002Fdata\u002Foutput\u002Fpoints_buffered.gpkg\",\n}\n\nresult = processing.run(\"native:buffer\", params)\n\nprint(\"Result keys:\", list(result.keys()))\nprint(\"Output written to:\", result[\"OUTPUT\"])\n",[38,719,720,726,730,740,754,769,780,791,803,808,812,827,831,850],{"__ignoreMap":415},[419,721,722,724],{"class":213,"line":421},[419,723,425],{"class":424},[419,725,655],{"class":428},[419,727,728],{"class":213,"line":432},[419,729,450],{"emptyLinePlaceholder":449},[419,731,732,735,737],{"class":213,"line":446},[419,733,734],{"class":428},"params ",[419,736,466],{"class":424},[419,738,739],{"class":428}," {\n",[419,741,742,745,748,751],{"class":213,"line":453},[419,743,744],{"class":496},"    \"INPUT\"",[419,746,747],{"class":428},": ",[419,749,750],{"class":496},"\"\u002Fdata\u002Fpoints.gpkg\"",[419,752,753],{"class":428},",\n",[419,755,756,759,761,763,766],{"class":213,"line":460},[419,757,758],{"class":496},"    \"DISTANCE\"",[419,760,747],{"class":428},[419,762,269],{"class":472},[419,764,765],{"class":428},",            ",[419,767,768],{"class":456},"# in the layer's CRS units\n",[419,770,771,774,776,778],{"class":213,"line":479},[419,772,773],{"class":496},"    \"SEGMENTS\"",[419,775,747],{"class":428},[419,777,249],{"class":472},[419,779,753],{"class":428},[419,781,782,785,787,789],{"class":213,"line":484},[419,783,784],{"class":496},"    \"DISSOLVE\"",[419,786,747],{"class":428},[419,788,473],{"class":472},[419,790,753],{"class":428},[419,792,793,796,798,801],{"class":213,"line":490},[419,794,795],{"class":496},"    \"OUTPUT\"",[419,797,747],{"class":428},[419,799,800],{"class":496},"\"\u002Fdata\u002Foutput\u002Fpoints_buffered.gpkg\"",[419,802,753],{"class":428},[419,804,805],{"class":213,"line":508},[419,806,807],{"class":428},"}\n",[419,809,810],{"class":213,"line":514},[419,811,450],{"emptyLinePlaceholder":449},[419,813,814,817,819,822,824],{"class":213,"line":519},[419,815,816],{"class":428},"result ",[419,818,466],{"class":424},[419,820,821],{"class":428}," processing.run(",[419,823,667],{"class":496},[419,825,826],{"class":428},", params)\n",[419,828,829],{"class":213,"line":525},[419,830,450],{"emptyLinePlaceholder":449},[419,832,833,836,839,842,844,847],{"class":213,"line":536},[419,834,835],{"class":472},"print",[419,837,838],{"class":428},"(",[419,840,841],{"class":496},"\"Result keys:\"",[419,843,500],{"class":428},[419,845,846],{"class":472},"list",[419,848,849],{"class":428},"(result.keys()))\n",[419,851,852,854,856,859,862,865],{"class":213,"line":549},[419,853,835],{"class":472},[419,855,838],{"class":428},[419,857,858],{"class":496},"\"Output written to:\"",[419,860,861],{"class":428},", result[",[419,863,864],{"class":496},"\"OUTPUT\"",[419,866,867],{"class":428},"])\n",[14,869,870,588,872,874,875,877,878,880,881,884,885,888],{},[43,871,587],{},[38,873,53],{}," executes synchronously and returns a dict keyed by the algorithm's output names. When ",[38,876,689],{}," was a file path, ",[38,879,305],{}," is that path string; when it was ",[38,882,883],{},"TEMPORARY_OUTPUT",", it is an in-memory layer reference. Inspecting ",[38,886,887],{},"result.keys()"," reveals every output an algorithm produced — some return extra outputs such as a count or a report file alongside the main layer.",[14,890,891],{},"To use the result immediately, load it as a layer:",[410,893,895],{"className":412,"code":894,"language":414,"meta":415,"style":415},"from qgis.core import QgsVectorLayer\n\nout_layer = QgsVectorLayer(result[\"OUTPUT\"], \"buffered\", \"ogr\")\nprint(\"Feature count:\", out_layer.featureCount())\n",[38,896,897,908,912,937],{"__ignoreMap":415},[419,898,899,901,903,905],{"class":213,"line":421},[419,900,435],{"class":424},[419,902,438],{"class":428},[419,904,425],{"class":424},[419,906,907],{"class":428}," QgsVectorLayer\n",[419,909,910],{"class":213,"line":432},[419,911,450],{"emptyLinePlaceholder":449},[419,913,914,917,919,922,924,927,930,932,935],{"class":213,"line":446},[419,915,916],{"class":428},"out_layer ",[419,918,466],{"class":424},[419,920,921],{"class":428}," QgsVectorLayer(result[",[419,923,864],{"class":496},[419,925,926],{"class":428},"], ",[419,928,929],{"class":496},"\"buffered\"",[419,931,500],{"class":428},[419,933,934],{"class":496},"\"ogr\"",[419,936,476],{"class":428},[419,938,939,941,943,946],{"class":213,"line":453},[419,940,835],{"class":472},[419,942,838],{"class":428},[419,944,945],{"class":496},"\"Feature count:\"",[419,947,948],{"class":428},", out_layer.featureCount())\n",[14,950,951,953,954,957,958,960,961,963,964,968,969,971,972,386],{},[43,952,587],{}," A file-path output is opened with the ",[38,955,956],{},"ogr"," provider. A ",[38,959,883],{}," result is already a layer object and needs no reloading — assign ",[38,962,305],{}," directly. This is the same dictionary pattern used when ",[20,965,967],{"href":966},"\u002Fspatial-data-processing-automation\u002Fchaining-processing-algorithms\u002Fchain-buffer-and-clip-pyqgis\u002F","chaining processing algorithms",", where one step's ",[38,970,689],{}," feeds the next step's ",[38,973,677],{},[350,975,977],{"id":976},"a-complete-runnable-script","A Complete Runnable Script",[14,979,980,981,983],{},"Putting the pieces together, including a clean shutdown with ",[38,982,320],{},":",[410,985,987],{"className":412,"code":986,"language":414,"meta":415,"style":415},"import sys\nfrom qgis.core import QgsApplication, QgsVectorLayer\n\nqgs = QgsApplication([], False)\nQgsApplication.setPrefixPath(\"\u002Fusr\", True)\nqgs.initQgis()\n\nsys.path.append(\"\u002Fusr\u002Fshare\u002Fqgis\u002Fpython\u002Fplugins\")\nfrom processing.core.Processing import Processing\nimport processing\nfrom qgis.analysis import QgsNativeAlgorithms\n\nProcessing.initialize()\nQgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())\n\ntry:\n    result = processing.run(\"native:buffer\", {\n        \"INPUT\": \"\u002Fdata\u002Fpoints.gpkg\",\n        \"DISTANCE\": 250,\n        \"SEGMENTS\": 8,\n        \"DISSOLVE\": False,\n        \"OUTPUT\": \"\u002Fdata\u002Foutput\u002Fpoints_buffered.gpkg\",\n    })\n    layer = QgsVectorLayer(result[\"OUTPUT\"], \"buffered\", \"ogr\")\n    print(f\"Done: {layer.featureCount()} features\")\nfinally:\n    qgs.exitQgis()\n",[38,988,989,995,1006,1010,1022,1034,1038,1042,1050,1060,1066,1076,1080,1084,1088,1092,1100,1114,1125,1137,1149,1161,1173,1179,1201,1229,1237],{"__ignoreMap":415},[419,990,991,993],{"class":213,"line":421},[419,992,425],{"class":424},[419,994,429],{"class":428},[419,996,997,999,1001,1003],{"class":213,"line":432},[419,998,435],{"class":424},[419,1000,438],{"class":428},[419,1002,425],{"class":424},[419,1004,1005],{"class":428}," QgsApplication, QgsVectorLayer\n",[419,1007,1008],{"class":213,"line":446},[419,1009,450],{"emptyLinePlaceholder":449},[419,1011,1012,1014,1016,1018,1020],{"class":213,"line":453},[419,1013,463],{"class":428},[419,1015,466],{"class":424},[419,1017,469],{"class":428},[419,1019,473],{"class":472},[419,1021,476],{"class":428},[419,1023,1024,1026,1028,1030,1032],{"class":213,"line":460},[419,1025,493],{"class":428},[419,1027,497],{"class":496},[419,1029,500],{"class":428},[419,1031,503],{"class":472},[419,1033,476],{"class":428},[419,1035,1036],{"class":213,"line":479},[419,1037,511],{"class":428},[419,1039,1040],{"class":213,"line":484},[419,1041,450],{"emptyLinePlaceholder":449},[419,1043,1044,1046,1048],{"class":213,"line":490},[419,1045,528],{"class":428},[419,1047,531],{"class":496},[419,1049,476],{"class":428},[419,1051,1052,1054,1056,1058],{"class":213,"line":508},[419,1053,435],{"class":424},[419,1055,541],{"class":428},[419,1057,425],{"class":424},[419,1059,546],{"class":428},[419,1061,1062,1064],{"class":213,"line":514},[419,1063,425],{"class":424},[419,1065,655],{"class":428},[419,1067,1068,1070,1072,1074],{"class":213,"line":519},[419,1069,435],{"class":424},[419,1071,571],{"class":428},[419,1073,425],{"class":424},[419,1075,576],{"class":428},[419,1077,1078],{"class":213,"line":525},[419,1079,450],{"emptyLinePlaceholder":449},[419,1081,1082],{"class":213,"line":536},[419,1083,552],{"class":428},[419,1085,1086],{"class":213,"line":549},[419,1087,582],{"class":428},[419,1089,1090],{"class":213,"line":555},[419,1091,450],{"emptyLinePlaceholder":449},[419,1093,1094,1097],{"class":213,"line":560},[419,1095,1096],{"class":424},"try",[419,1098,1099],{"class":428},":\n",[419,1101,1102,1105,1107,1109,1111],{"class":213,"line":566},[419,1103,1104],{"class":428},"    result ",[419,1106,466],{"class":424},[419,1108,821],{"class":428},[419,1110,667],{"class":496},[419,1112,1113],{"class":428},", {\n",[419,1115,1116,1119,1121,1123],{"class":213,"line":579},[419,1117,1118],{"class":496},"        \"INPUT\"",[419,1120,747],{"class":428},[419,1122,750],{"class":496},[419,1124,753],{"class":428},[419,1126,1128,1131,1133,1135],{"class":213,"line":1127},19,[419,1129,1130],{"class":496},"        \"DISTANCE\"",[419,1132,747],{"class":428},[419,1134,269],{"class":472},[419,1136,753],{"class":428},[419,1138,1140,1143,1145,1147],{"class":213,"line":1139},20,[419,1141,1142],{"class":496},"        \"SEGMENTS\"",[419,1144,747],{"class":428},[419,1146,249],{"class":472},[419,1148,753],{"class":428},[419,1150,1152,1155,1157,1159],{"class":213,"line":1151},21,[419,1153,1154],{"class":496},"        \"DISSOLVE\"",[419,1156,747],{"class":428},[419,1158,473],{"class":472},[419,1160,753],{"class":428},[419,1162,1164,1167,1169,1171],{"class":213,"line":1163},22,[419,1165,1166],{"class":496},"        \"OUTPUT\"",[419,1168,747],{"class":428},[419,1170,800],{"class":496},[419,1172,753],{"class":428},[419,1174,1176],{"class":213,"line":1175},23,[419,1177,1178],{"class":428},"    })\n",[419,1180,1182,1185,1187,1189,1191,1193,1195,1197,1199],{"class":213,"line":1181},24,[419,1183,1184],{"class":428},"    layer ",[419,1186,466],{"class":424},[419,1188,921],{"class":428},[419,1190,864],{"class":496},[419,1192,926],{"class":428},[419,1194,929],{"class":496},[419,1196,500],{"class":428},[419,1198,934],{"class":496},[419,1200,476],{"class":428},[419,1202,1204,1207,1209,1212,1215,1218,1221,1224,1227],{"class":213,"line":1203},25,[419,1205,1206],{"class":472},"    print",[419,1208,838],{"class":428},[419,1210,1211],{"class":424},"f",[419,1213,1214],{"class":496},"\"Done: ",[419,1216,1217],{"class":472},"{",[419,1219,1220],{"class":428},"layer.featureCount()",[419,1222,1223],{"class":472},"}",[419,1225,1226],{"class":496}," features\"",[419,1228,476],{"class":428},[419,1230,1232,1235],{"class":213,"line":1231},26,[419,1233,1234],{"class":424},"finally",[419,1236,1099],{"class":428},[419,1238,1240],{"class":213,"line":1239},27,[419,1241,1242],{"class":428},"    qgs.exitQgis()\n",[14,1244,1245,1247,1248,1251,1252,1254,1255,1257],{},[43,1246,587],{}," The ",[38,1249,1250],{},"try\u002Ffinally"," guarantees ",[38,1253,320],{}," runs even if the algorithm raises, releasing QGIS resources and flushing any open data sources. Omitting ",[38,1256,320],{}," can leave file locks or incomplete writes in long-running batch jobs. This skeleton is the template every standalone Processing script should follow.",[14,1259,1260],{},"The parameter dictionary is where most first attempts fail, because three different kinds of value are accepted for the same key and only some of them are interchangeable.",[14,1262,1263],{},[66,1264,1267,1270,1273,1277,1283,1288,1292,1298,1303,1305,1309,1313,1316,1319,1323,1326,1329,1332,1336],{"viewBox":1265,"role":69,"ariaLabel":1266,"xmlns":71},"0 0 760 244","Four accepted forms for an INPUT parameter — a layer object, a file path, a path with a layername suffix, and a selection-aware source definition — with what each implies",[74,1268,1269],{},"Four things INPUT will accept",[78,1271,1272],{},"A layer object uses the already-loaded layer and honours nothing about selection. A bare file path opens the source fresh, which is what a headless script needs. A path with a layername suffix picks one layer out of a multi-layer GeoPackage. A processing feature source definition wraps a layer identifier and can restrict the run to selected features only.",[82,1274],{"x":84,"y":84,"width":1275,"height":1276,"fill":87},"760","244",[89,1278,1282],{"x":1279,"y":1280,"style":1281,"fill":93,"textAnchor":95},"380","26","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","Same key, four accepted values, different behaviour",[82,1284],{"x":1285,"y":1286,"width":1287,"height":1286,"rx":249,"fill":110,"stroke":125,"style":126},"16","46","728",[89,1289,1291],{"x":121,"y":123,"style":1290,"fill":100},"font-size:11px;font-family:monospace","\"INPUT\": layer",[89,1293,1297],{"x":1294,"y":1295,"style":1296,"fill":125},"300","70","font-size:11.5px;font-weight:bold;font-family:sans-serif","a loaded QgsVectorLayer",[89,1299,1302],{"x":1300,"y":1295,"style":1301,"fill":100},"560","font-size:11px;font-family:sans-serif","reuses data already in memory",[82,1304],{"x":1285,"y":122,"width":1287,"height":1286,"rx":249,"fill":110,"stroke":250,"style":126},[89,1306,1308],{"x":121,"y":1307,"style":1290,"fill":100},"132","\"INPUT\": \"\u002Fdata\u002Froads.shp\"",[89,1310,1312],{"x":1294,"y":1311,"style":1296,"fill":250},"126","a bare file path",[89,1314,1315],{"x":1300,"y":1311,"style":1301,"fill":100},"opens fresh · headless-safe",[82,1317],{"x":1285,"y":1318,"width":1287,"height":1286,"rx":249,"fill":110,"stroke":299,"style":126},"158",[89,1320,1322],{"x":121,"y":1321,"style":1290,"fill":100},"188","\"…gpkg|layername=roads\"",[89,1324,1325],{"x":1294,"y":149,"style":1296,"fill":299},"one layer of many",[89,1327,1328],{"x":1300,"y":149,"style":1301,"fill":100},"required for GeoPackage",[82,1330],{"x":1285,"y":1331,"width":1287,"height":245,"rx":249,"fill":110,"stroke":111,"style":126},"214",[89,1333,1335],{"x":121,"y":1334,"style":1290,"fill":100},"234","QgsProcessingFeatureSourceDefinition(id, selectedFeaturesOnly=True)",[89,1337,1338],{"x":1300,"y":1334,"style":1301,"fill":111},"honours the selection",[14,1340,1341],{},"The last row is the one people miss: passing a layer object never restricts the run to the selection, no matter what is highlighted on the canvas. Only the explicit source definition does that.",[350,1343,1345],{"id":1344},"run-algorithms-in-a-batch-loop","Run Algorithms in a Batch Loop",[14,1347,1348,1349,1351],{},"The whole point of scripting Processing is to repeat an algorithm across many inputs without touching the GUI. Once the bootstrap is in place, wrap ",[38,1350,53],{}," in a loop over a folder of files, collecting outputs and logging failures so one bad file does not abort the run:",[410,1353,1355],{"className":412,"code":1354,"language":414,"meta":415,"style":415},"from pathlib import Path\nimport processing\n\nsource_dir = Path(\"\u002Fdata\u002Fpoints\")\noutput_dir = Path(\"\u002Fdata\u002Foutput\")\noutput_dir.mkdir(parents=True, exist_ok=True)\n\nresults, errors = [], []\nfor src in sorted(source_dir.glob(\"*.gpkg\")):\n    out_path = output_dir \u002F f\"{src.stem}_buffered.gpkg\"\n    try:\n        processing.run(\"native:buffer\", {\n            \"INPUT\": str(src),\n            \"DISTANCE\": 250,\n            \"SEGMENTS\": 8,\n            \"DISSOLVE\": False,\n            \"OUTPUT\": str(out_path),\n        })\n        results.append(out_path)\n    except Exception as exc:\n        errors.append((src.name, str(exc)))\n\nprint(f\"Succeeded: {len(results)}  Failed: {len(errors)}\")\nfor name, msg in errors:\n    print(f\"  {name}: {msg}\")\n",[38,1356,1357,1369,1375,1379,1394,1408,1432,1436,1446,1469,1497,1504,1513,1526,1537,1548,1559,1571,1576,1581,1595,1605,1609,1642,1654],{"__ignoreMap":415},[419,1358,1359,1361,1364,1366],{"class":213,"line":421},[419,1360,435],{"class":424},[419,1362,1363],{"class":428}," pathlib ",[419,1365,425],{"class":424},[419,1367,1368],{"class":428}," Path\n",[419,1370,1371,1373],{"class":213,"line":432},[419,1372,425],{"class":424},[419,1374,655],{"class":428},[419,1376,1377],{"class":213,"line":446},[419,1378,450],{"emptyLinePlaceholder":449},[419,1380,1381,1384,1386,1389,1392],{"class":213,"line":453},[419,1382,1383],{"class":428},"source_dir ",[419,1385,466],{"class":424},[419,1387,1388],{"class":428}," Path(",[419,1390,1391],{"class":496},"\"\u002Fdata\u002Fpoints\"",[419,1393,476],{"class":428},[419,1395,1396,1399,1401,1403,1406],{"class":213,"line":460},[419,1397,1398],{"class":428},"output_dir ",[419,1400,466],{"class":424},[419,1402,1388],{"class":428},[419,1404,1405],{"class":496},"\"\u002Fdata\u002Foutput\"",[419,1407,476],{"class":428},[419,1409,1410,1413,1417,1419,1421,1423,1426,1428,1430],{"class":213,"line":479},[419,1411,1412],{"class":428},"output_dir.mkdir(",[419,1414,1416],{"class":1415},"s9osk","parents",[419,1418,466],{"class":424},[419,1420,503],{"class":472},[419,1422,500],{"class":428},[419,1424,1425],{"class":1415},"exist_ok",[419,1427,466],{"class":424},[419,1429,503],{"class":472},[419,1431,476],{"class":428},[419,1433,1434],{"class":213,"line":484},[419,1435,450],{"emptyLinePlaceholder":449},[419,1437,1438,1441,1443],{"class":213,"line":490},[419,1439,1440],{"class":428},"results, errors ",[419,1442,466],{"class":424},[419,1444,1445],{"class":428}," [], []\n",[419,1447,1448,1451,1454,1457,1460,1463,1466],{"class":213,"line":508},[419,1449,1450],{"class":424},"for",[419,1452,1453],{"class":428}," src ",[419,1455,1456],{"class":424},"in",[419,1458,1459],{"class":472}," sorted",[419,1461,1462],{"class":428},"(source_dir.glob(",[419,1464,1465],{"class":496},"\"*.gpkg\"",[419,1467,1468],{"class":428},")):\n",[419,1470,1471,1474,1476,1479,1481,1484,1487,1489,1492,1494],{"class":213,"line":514},[419,1472,1473],{"class":428},"    out_path ",[419,1475,466],{"class":424},[419,1477,1478],{"class":428}," output_dir ",[419,1480,22],{"class":424},[419,1482,1483],{"class":424}," f",[419,1485,1486],{"class":496},"\"",[419,1488,1217],{"class":472},[419,1490,1491],{"class":428},"src.stem",[419,1493,1223],{"class":472},[419,1495,1496],{"class":496},"_buffered.gpkg\"\n",[419,1498,1499,1502],{"class":213,"line":519},[419,1500,1501],{"class":424},"    try",[419,1503,1099],{"class":428},[419,1505,1506,1509,1511],{"class":213,"line":525},[419,1507,1508],{"class":428},"        processing.run(",[419,1510,667],{"class":496},[419,1512,1113],{"class":428},[419,1514,1515,1518,1520,1523],{"class":213,"line":536},[419,1516,1517],{"class":496},"            \"INPUT\"",[419,1519,747],{"class":428},[419,1521,1522],{"class":472},"str",[419,1524,1525],{"class":428},"(src),\n",[419,1527,1528,1531,1533,1535],{"class":213,"line":549},[419,1529,1530],{"class":496},"            \"DISTANCE\"",[419,1532,747],{"class":428},[419,1534,269],{"class":472},[419,1536,753],{"class":428},[419,1538,1539,1542,1544,1546],{"class":213,"line":555},[419,1540,1541],{"class":496},"            \"SEGMENTS\"",[419,1543,747],{"class":428},[419,1545,249],{"class":472},[419,1547,753],{"class":428},[419,1549,1550,1553,1555,1557],{"class":213,"line":560},[419,1551,1552],{"class":496},"            \"DISSOLVE\"",[419,1554,747],{"class":428},[419,1556,473],{"class":472},[419,1558,753],{"class":428},[419,1560,1561,1564,1566,1568],{"class":213,"line":566},[419,1562,1563],{"class":496},"            \"OUTPUT\"",[419,1565,747],{"class":428},[419,1567,1522],{"class":472},[419,1569,1570],{"class":428},"(out_path),\n",[419,1572,1573],{"class":213,"line":579},[419,1574,1575],{"class":428},"        })\n",[419,1577,1578],{"class":213,"line":1127},[419,1579,1580],{"class":428},"        results.append(out_path)\n",[419,1582,1583,1586,1589,1592],{"class":213,"line":1139},[419,1584,1585],{"class":424},"    except",[419,1587,1588],{"class":472}," Exception",[419,1590,1591],{"class":424}," as",[419,1593,1594],{"class":428}," exc:\n",[419,1596,1597,1600,1602],{"class":213,"line":1151},[419,1598,1599],{"class":428},"        errors.append((src.name, ",[419,1601,1522],{"class":472},[419,1603,1604],{"class":428},"(exc)))\n",[419,1606,1607],{"class":213,"line":1163},[419,1608,450],{"emptyLinePlaceholder":449},[419,1610,1611,1613,1615,1617,1620,1623,1626,1628,1631,1633,1636,1638,1640],{"class":213,"line":1175},[419,1612,835],{"class":472},[419,1614,838],{"class":428},[419,1616,1211],{"class":424},[419,1618,1619],{"class":496},"\"Succeeded: ",[419,1621,1622],{"class":472},"{len",[419,1624,1625],{"class":428},"(results)",[419,1627,1223],{"class":472},[419,1629,1630],{"class":496},"  Failed: ",[419,1632,1622],{"class":472},[419,1634,1635],{"class":428},"(errors)",[419,1637,1223],{"class":472},[419,1639,1486],{"class":496},[419,1641,476],{"class":428},[419,1643,1644,1646,1649,1651],{"class":213,"line":1181},[419,1645,1450],{"class":424},[419,1647,1648],{"class":428}," name, msg ",[419,1650,1456],{"class":424},[419,1652,1653],{"class":428}," errors:\n",[419,1655,1656,1658,1660,1662,1665,1667,1670,1672,1674,1676,1679,1681,1683],{"class":213,"line":1203},[419,1657,1206],{"class":472},[419,1659,838],{"class":428},[419,1661,1211],{"class":424},[419,1663,1664],{"class":496},"\"  ",[419,1666,1217],{"class":472},[419,1668,1669],{"class":428},"name",[419,1671,1223],{"class":472},[419,1673,747],{"class":496},[419,1675,1217],{"class":472},[419,1677,1678],{"class":428},"msg",[419,1680,1223],{"class":472},[419,1682,1486],{"class":496},[419,1684,476],{"class":428},[14,1686,1687,588,1689,1692,1693,1696,1697,1699,1700,1702,1703,386],{},[43,1688,587],{},[38,1690,1691],{},"Path.glob(\"*.gpkg\")"," enumerates inputs; the ",[38,1694,1695],{},"try\u002Fexcept"," around each ",[38,1698,53],{}," isolates per-file failures so the loop continues and reports them at the end. Building output names from ",[38,1701,1491],{}," keeps results traceable to their source. This is the standalone-script counterpart to the interactive Console patterns covered across ",[20,1704,32],{"href":31},[350,1706,1708],{"id":1707},"capture-progress-and-feedback","Capture Progress and Feedback",[14,1710,1711,1712,1715,1716,1718],{},"Long batch jobs benefit from a feedback object that surfaces progress and any algorithm warnings. Pass a ",[38,1713,1714],{},"QgsProcessingFeedback"," to ",[38,1717,53],{}," to capture them programmatically:",[410,1720,1722],{"className":412,"code":1721,"language":414,"meta":415,"style":415},"import processing\nfrom qgis.core import QgsProcessingFeedback\n\n\nclass LoggingFeedback(QgsProcessingFeedback):\n    def pushInfo(self, info):\n        print(\"INFO:\", info)\n\n    def reportError(self, error, fatalError=False):\n        print(\"ERROR:\", error)\n\n\nresult = processing.run(\n    \"native:buffer\",\n    {\n        \"INPUT\": \"\u002Fdata\u002Fpoints.gpkg\",\n        \"DISTANCE\": 250,\n        \"SEGMENTS\": 8,\n        \"DISSOLVE\": False,\n        \"OUTPUT\": \"\u002Fdata\u002Foutput\u002Fpoints_buffered.gpkg\",\n    },\n    feedback=LoggingFeedback(),\n)\n",[38,1723,1724,1730,1741,1745,1749,1765,1776,1789,1793,1809,1821,1825,1829,1838,1845,1850,1860,1870,1880,1890,1900,1905,1915],{"__ignoreMap":415},[419,1725,1726,1728],{"class":213,"line":421},[419,1727,425],{"class":424},[419,1729,655],{"class":428},[419,1731,1732,1734,1736,1738],{"class":213,"line":432},[419,1733,435],{"class":424},[419,1735,438],{"class":428},[419,1737,425],{"class":424},[419,1739,1740],{"class":428}," QgsProcessingFeedback\n",[419,1742,1743],{"class":213,"line":446},[419,1744,450],{"emptyLinePlaceholder":449},[419,1746,1747],{"class":213,"line":453},[419,1748,450],{"emptyLinePlaceholder":449},[419,1750,1751,1754,1758,1760,1762],{"class":213,"line":460},[419,1752,1753],{"class":424},"class",[419,1755,1757],{"class":1756},"svObZ"," LoggingFeedback",[419,1759,838],{"class":428},[419,1761,1714],{"class":1756},[419,1763,1764],{"class":428},"):\n",[419,1766,1767,1770,1773],{"class":213,"line":479},[419,1768,1769],{"class":424},"    def",[419,1771,1772],{"class":1756}," pushInfo",[419,1774,1775],{"class":428},"(self, info):\n",[419,1777,1778,1781,1783,1786],{"class":213,"line":484},[419,1779,1780],{"class":472},"        print",[419,1782,838],{"class":428},[419,1784,1785],{"class":496},"\"INFO:\"",[419,1787,1788],{"class":428},", info)\n",[419,1790,1791],{"class":213,"line":490},[419,1792,450],{"emptyLinePlaceholder":449},[419,1794,1795,1797,1800,1803,1805,1807],{"class":213,"line":508},[419,1796,1769],{"class":424},[419,1798,1799],{"class":1756}," reportError",[419,1801,1802],{"class":428},"(self, error, fatalError",[419,1804,466],{"class":424},[419,1806,473],{"class":472},[419,1808,1764],{"class":428},[419,1810,1811,1813,1815,1818],{"class":213,"line":514},[419,1812,1780],{"class":472},[419,1814,838],{"class":428},[419,1816,1817],{"class":496},"\"ERROR:\"",[419,1819,1820],{"class":428},", error)\n",[419,1822,1823],{"class":213,"line":519},[419,1824,450],{"emptyLinePlaceholder":449},[419,1826,1827],{"class":213,"line":525},[419,1828,450],{"emptyLinePlaceholder":449},[419,1830,1831,1833,1835],{"class":213,"line":536},[419,1832,816],{"class":428},[419,1834,466],{"class":424},[419,1836,1837],{"class":428}," processing.run(\n",[419,1839,1840,1843],{"class":213,"line":549},[419,1841,1842],{"class":496},"    \"native:buffer\"",[419,1844,753],{"class":428},[419,1846,1847],{"class":213,"line":555},[419,1848,1849],{"class":428},"    {\n",[419,1851,1852,1854,1856,1858],{"class":213,"line":560},[419,1853,1118],{"class":496},[419,1855,747],{"class":428},[419,1857,750],{"class":496},[419,1859,753],{"class":428},[419,1861,1862,1864,1866,1868],{"class":213,"line":566},[419,1863,1130],{"class":496},[419,1865,747],{"class":428},[419,1867,269],{"class":472},[419,1869,753],{"class":428},[419,1871,1872,1874,1876,1878],{"class":213,"line":579},[419,1873,1142],{"class":496},[419,1875,747],{"class":428},[419,1877,249],{"class":472},[419,1879,753],{"class":428},[419,1881,1882,1884,1886,1888],{"class":213,"line":1127},[419,1883,1154],{"class":496},[419,1885,747],{"class":428},[419,1887,473],{"class":472},[419,1889,753],{"class":428},[419,1891,1892,1894,1896,1898],{"class":213,"line":1139},[419,1893,1166],{"class":496},[419,1895,747],{"class":428},[419,1897,800],{"class":496},[419,1899,753],{"class":428},[419,1901,1902],{"class":213,"line":1151},[419,1903,1904],{"class":428},"    },\n",[419,1906,1907,1910,1912],{"class":213,"line":1163},[419,1908,1909],{"class":1415},"    feedback",[419,1911,466],{"class":424},[419,1913,1914],{"class":428},"LoggingFeedback(),\n",[419,1916,1917],{"class":213,"line":1175},[419,1918,476],{"class":428},[14,1920,1921,1923,1924,1926,1927,22,1930,1933,1934,1937,1938,1940],{},[43,1922,587],{}," Subclassing ",[38,1925,1714],{}," and overriding ",[38,1928,1929],{},"pushInfo",[38,1931,1932],{},"reportError"," routes the algorithm's internal messages to your own logger — invaluable when a headless job runs unattended and you need a record of what each step reported. The ",[38,1935,1936],{},"feedback"," keyword is accepted by every ",[38,1939,53],{}," call.",[350,1942,1944],{"id":1943},"which-run-function-to-call","Which run function to call",[14,1946,1947,1950],{},[38,1948,1949],{},"processing"," exposes three entry points, and choosing the wrong one is the difference between a script that works in the Console and one that crashes headless.",[14,1952,1953],{},[66,1954,1957,1960,1963,1965,1968,1974,1980,1984,1988],{"viewBox":1955,"role":69,"ariaLabel":1956,"xmlns":71},"0 0 760 234","Three processing entry points compared: run, runAndLoadResults and createAlgorithmDialog, by what they return and whether they need a GUI",[74,1958,1959],{},"run, runAndLoadResults and the dialog",[78,1961,1962],{},"processing.run returns a results dictionary and needs no GUI, making it the choice for scripts. processing.runAndLoadResults additionally adds the outputs to the project layer tree and therefore requires a running desktop. createAlgorithmDialog opens the algorithm's own parameter dialog for the user to fill in, which is only meaningful inside QGIS Desktop.",[82,1964],{"x":84,"y":84,"width":1275,"height":1334,"fill":87},[89,1966,1967],{"x":1279,"y":1280,"style":1281,"fill":93,"textAnchor":95},"Only one of these is safe in a headless script",[213,1969],{"x1":1970,"y1":106,"x2":1971,"y2":106,"stroke":1972,"style":1973},"256","744","#59645f","stroke-width:1.5",[89,1975,1979],{"x":1276,"y":1976,"style":1977,"fill":93,"textAnchor":1978},"58","text-anchor:end;font-size:11.5px;font-weight:bold;font-family:sans-serif","end","function",[89,1981,1983],{"x":91,"y":1976,"style":1982,"fill":93,"textAnchor":95},"text-anchor:middle;font-size:11.5px;font-weight:bold;font-family:sans-serif","returns",[89,1985,1987],{"x":1986,"y":1976,"style":1982,"fill":93,"textAnchor":95},"640","needs a GUI",[1989,1990,1992,1996,2000,2004,2008,2011,2014,2019,2022],"g",{"style":1991},"font-size:11.5px;font-family:sans-serif",[89,1993,1995],{"x":1276,"y":122,"style":1994,"fill":250,"textAnchor":1978},"text-anchor:end;font-weight:bold;font-family:monospace","run()",[89,1997,1999],{"x":91,"y":122,"style":1998,"fill":100,"textAnchor":95},"text-anchor:middle","a results dictionary",[89,2001,2003],{"x":1986,"y":122,"style":2002,"fill":250,"textAnchor":95},"text-anchor:middle;font-weight:bold","no",[89,2005,2007],{"x":1276,"y":2006,"style":1994,"fill":299,"textAnchor":1978},"146","runAndLoadResults()",[89,2009,2010],{"x":91,"y":2006,"style":1998,"fill":100,"textAnchor":95},"the same, plus layers added",[89,2012,2013],{"x":1986,"y":2006,"style":2002,"fill":299,"textAnchor":95},"yes",[89,2015,2018],{"x":1276,"y":2016,"style":1994,"fill":2017,"textAnchor":1978},"190","#b91c1c","createAlgorithmDialog()",[89,2020,2021],{"x":91,"y":2016,"style":1998,"fill":100,"textAnchor":95},"a dialog for the user",[89,2023,2013],{"x":1986,"y":2016,"style":2002,"fill":2017,"textAnchor":95},[14,2025,2026,2028],{},[38,2027,2007],{}," is convenient in the Python Console and a liability in anything scheduled — there is no layer tree to add to, and the call fails in a way that points at Processing rather than at the real cause.",[350,2030,2032],{"id":2031},"qgis-version-compatibility","QGIS Version Compatibility",[14,2034,2035,2036,2039],{},"The code targets ",[43,2037,2038],{},"QGIS 3.34 LTR"," (Python 3.12).",[2041,2042,2043,2059],"table",{},[2044,2045,2046],"thead",{},[2047,2048,2049,2053,2056],"tr",{},[2050,2051,2052],"th",{},"QGIS version",[2050,2054,2055],{},"Python",[2050,2057,2058],{},"Notes",[2060,2061,2062,2079,2090],"tbody",{},[2047,2063,2064,2068,2071],{},[2065,2066,2067],"td",{},"3.28 LTR",[2065,2069,2070],{},"3.9",[2065,2072,2073,2074,2076,2077,386],{},"Identical bootstrap; same ",[38,2075,617],{}," and ",[38,2078,403],{},[2047,2080,2081,2084,2087],{},[2065,2082,2083],{},"3.34 LTR",[2065,2085,2086],{},"3.12",[2065,2088,2089],{},"Baseline for this page.",[2047,2091,2092,2095,2097],{},[2065,2093,2094],{},"3.40 \u002F 3.44",[2065,2096,2086],{},[2065,2098,2099],{},"Same initialization API; algorithm IDs unchanged.",[14,2101,2102,2103,500,2105,500,2108,500,2111,2113],{},"The standalone initialization sequence — ",[38,2104,49],{},[38,2106,2107],{},"initQgis",[38,2109,2110],{},"Processing.initialize",[38,2112,621],{}," — has been stable across the entire 3.x line. Only the prefix path differs per platform and install.",[350,2115,2117],{"id":2116},"troubleshooting","Troubleshooting",[355,2119,2120,2133,2141,2153,2166],{},[358,2121,2122,2127,2128,614,2130,2132],{},[43,2123,2124,386],{},[38,2125,2126],{},"Algorithm native:buffer not found"," You skipped ",[38,2129,621],{},[38,2131,617],{}," alone does not register the native provider.",[358,2134,2135,2140],{},[43,2136,2137,386],{},[38,2138,2139],{},"ModuleNotFoundError: No module named 'qgis'"," You are running system Python. Launch with the QGIS\u002FOSGeo4W Python instead.",[358,2142,2143,2148,2149,611,2151,386],{},[43,2144,2145,386],{},[38,2146,2147],{},"No module named 'processing'"," The plugins path is missing — append it to ",[38,2150,610],{},[38,2152,191],{},[358,2154,2155,588,2160,2162,2163,2165],{},[43,2156,2157,386],{},[38,2158,2159],{},"Application path not initialized",[38,2161,159],{}," points at the wrong directory or ",[38,2164,399],{}," was never called. Verify the prefix matches your install.",[358,2167,2168,2171,2172,2174],{},[43,2169,2170],{},"Output file already exists \u002F is locked."," A previous run left the GeoPackage open. Ensure ",[38,2173,320],{}," ran, or write to a fresh path.",[350,2176,2178],{"id":2177},"conclusion","Conclusion",[14,2180,2181,2182,2184,2185,2187,2188,2190,2191,2193,2194,2196,2197,2199,2200,2202],{},"Running a Processing algorithm from a standalone script is straightforward once the bootstrap is correct: start a headless ",[38,2183,49],{},", initialize Processing, and explicitly register ",[38,2186,403],{},". From there, ",[38,2189,63],{}," reveals exact parameter names, ",[38,2192,53],{}," executes the algorithm, and the returned dictionary's ",[38,2195,689],{}," key gives you the result to load or chain. Wrap it in ",[38,2198,1250],{}," with ",[38,2201,320],{}," and you have a reliable, GUI-free pattern ready for batch jobs, schedulers, and CI.",[350,2204,2206],{"id":2205},"frequently-asked-questions","Frequently Asked Questions",[14,2208,2209,2212,2213,396,2215,2217,2218,2220],{},[43,2210,2211],{},"Why does processing.run fail outside the QGIS Console?","\nThe Console pre-initializes QGIS and Processing for you. A standalone script must do it manually — create ",[38,2214,49],{},[38,2216,2107],{},", run ",[38,2219,617],{},", and add the native provider — before any algorithm call works.",[14,2222,2223,2226,2227,2229,2230,2233],{},[43,2224,2225],{},"How do I find an algorithm's parameter names?","\nCall ",[38,2228,642],{},", for example ",[38,2231,2232],{},"processing.algorithmHelp(\"native:buffer\")",". It prints every parameter key and the expected value type, which map directly to your parameters dictionary.",[14,2235,2236,2243,2244,22,2247,2250,2251,2253,2254,2256],{},[43,2237,2238,2239,2242],{},"What does result",[419,2240,2241],{},"'OUTPUT'"," contain?","\nIt is the algorithm's primary result: a file-path string if you supplied a path, or an in-memory ",[38,2245,2246],{},"QgsVectorLayer",[38,2248,2249],{},"QgsRasterLayer"," if you used ",[38,2252,883],{},". Check ",[38,2255,887],{}," for any additional outputs.",[14,2258,2259,2262,2263,2265],{},[43,2260,2261],{},"Do I need to call exitQgis()?","\nYes, in standalone scripts. It releases resources and flushes data sources. Wrap the work in ",[38,2264,1250],{}," so it runs even when an algorithm raises an exception.",[350,2267,2269],{"id":2268},"related","Related",[355,2271,2272,2277,2282,2291],{},[358,2273,2274,2276],{},[20,2275,32],{"href":31}," — parent guide to running algorithms across many datasets",[358,2278,2279,2281],{},[20,2280,385],{"href":384}," — set up the headless interpreter this recipe assumes",[358,2283,2284,2287,2288,2290],{},[20,2285,2286],{"href":966},"Chain a Buffer and Clip in PyQGIS"," — feed one algorithm's ",[38,2289,689],{}," into the next",[358,2292,2293,2297,2298,2300],{},[20,2294,2296],{"href":2295},"\u002Fqgis-plugin-development\u002Fprocessing-provider-plugins\u002Fwrite-custom-processing-algorithm-pyqgis\u002F","Write a Custom Processing Algorithm in PyQGIS"," — package your own ",[38,2299,407],{},"-style algorithm",[2302,2303,2304],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sjoCn, html code.shiki .sjoCn{--shiki-default:#9AA79F}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":415,"searchDepth":432,"depth":432,"links":2306},[2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319],{"id":352,"depth":432,"text":353},{"id":389,"depth":432,"text":390},{"id":635,"depth":432,"text":636},{"id":703,"depth":432,"text":704},{"id":976,"depth":432,"text":977},{"id":1344,"depth":432,"text":1345},{"id":1707,"depth":432,"text":1708},{"id":1943,"depth":432,"text":1944},{"id":2031,"depth":432,"text":2032},{"id":2116,"depth":432,"text":2117},{"id":2177,"depth":432,"text":2178},{"id":2205,"depth":432,"text":2206},{"id":2268,"depth":432,"text":2269},"Run a QGIS Processing algorithm from a standalone PyQGIS script. Initialize QgsApplication and Processing, discover parameters, and read result OUTPUT.","md",{"slug":2323,"type":2324,"breadcrumb":2325,"datePublished":2326,"dateModified":2327},"run-processing-algorithm-from-script","article","Run a Processing Algorithm from a Script","2025-03-18","2026-07-18","\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script",{"title":5,"description":2320},"spatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script\u002Findex","Hl_lceqDvS8Yiu8GGErzF1kc6vr_EwghTIegS2mU2Jo",1787823363514]