[{"data":1,"prerenderedAt":1846},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script":3},{"id":4,"title":5,"body":6,"description":1839,"extension":1840,"meta":1841,"navigation":148,"path":1842,"seo":1843,"stem":1844,"__hash__":1845},"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":1825},"minimark",[9,13,41,48,53,74,85,89,107,282,334,338,345,371,402,406,416,571,593,596,653,678,682,689,948,963,967,973,1307,1327,1331,1341,1541,1563,1567,1574,1634,1648,1652,1709,1713,1737,1741,1755,1768,1791,1800,1804,1821],[10,11,5],"h1",{"id":12},"run-a-processing-algorithm-from-a-script-in-pyqgis",[14,15,16,17,21,22,26,27,30,31,34,35,40],"p",{},"Inside the QGIS Python Console, ",[18,19,20],"code",{},"processing.run(...)"," just works because the application and the Processing framework are already initialized for you. In a ",[23,24,25],"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 ",[18,28,29],{},"QgsApplication",", initialize the Processing framework, and register the native algorithm provider before any ",[18,32,33],{},"processing.run"," call will succeed. This is the foundation of headless ",[36,37,39],"a",{"href":38},"\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002F","Batch Processing with PyQGIS",".",[14,42,43,44,47],{},"This page covers the exact bootstrap sequence, how to discover an algorithm's parameter names with ",[18,45,46],{},"processing.algorithmHelp",", how to run an algorithm, and how to read its output dictionary — then how to shut down cleanly.",[49,50,52],"h2",{"id":51},"prerequisites","Prerequisites",[54,55,56,60,71],"ul",{},[57,58,59],"li",{},"QGIS 3.34 LTR installed (bundled Python 3.12).",[57,61,62,63,66,67,70],{},"A terminal that can find the QGIS Python and libraries (use the ",[23,64,65],{},"OSGeo4W Shell"," on Windows, or ",[18,68,69],{},"python3"," from the QGIS install on Linux\u002FmacOS).",[57,72,73],{},"A test input layer to run an algorithm against.",[14,75,76,77,80,81,40],{},"Run standalone scripts with the QGIS-aware Python, not your system Python, or the ",[18,78,79],{},"qgis.core"," import will fail. For environment setup details see ",[36,82,84],{"href":83},"\u002Fpyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002Frunning-python-scripts-outside-qgis-desktop\u002F","Running Python Scripts Outside QGIS Desktop",[49,86,88],{"id":87},"initialize-qgsapplication-and-processing","Initialize QgsApplication and Processing",[14,90,91,92,94,95,98,99,102,103,106],{},"The bootstrap has four parts: create a headless ",[18,93,29],{},", call ",[18,96,97],{},"initQgis()",", initialize the Processing plugin, and add ",[18,100,101],{},"QgsNativeAlgorithms"," to the registry so the ",[18,104,105],{},"native:"," algorithms become available.",[108,109,114],"pre",{"className":110,"code":111,"language":112,"meta":113,"style":113},"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","",[18,115,116,129,143,150,157,176,181,187,205,211,216,222,233,246,252,257,263,276],{"__ignoreMap":113},[117,118,121,125],"span",{"class":119,"line":120},"line",1,[117,122,124],{"class":123},"snl16","import",[117,126,128],{"class":127},"s95oV"," sys\n",[117,130,132,135,138,140],{"class":119,"line":131},2,[117,133,134],{"class":123},"from",[117,136,137],{"class":127}," qgis.core ",[117,139,124],{"class":123},[117,141,142],{"class":127}," QgsApplication\n",[117,144,146],{"class":119,"line":145},3,[117,147,149],{"emptyLinePlaceholder":148},true,"\n",[117,151,153],{"class":119,"line":152},4,[117,154,156],{"class":155},"sAwPA","# 1. Headless application (second arg False = no GUI)\n",[117,158,160,163,166,169,173],{"class":119,"line":159},5,[117,161,162],{"class":127},"qgs ",[117,164,165],{"class":123},"=",[117,167,168],{"class":127}," QgsApplication([], ",[117,170,172],{"class":171},"sDLfK","False",[117,174,175],{"class":127},")\n",[117,177,179],{"class":119,"line":178},6,[117,180,149],{"emptyLinePlaceholder":148},[117,182,184],{"class":119,"line":183},7,[117,185,186],{"class":155},"# 2. Point at the install prefix; \"\" lets QGIS auto-detect on most setups\n",[117,188,190,193,197,200,203],{"class":119,"line":189},8,[117,191,192],{"class":127},"QgsApplication.setPrefixPath(",[117,194,196],{"class":195},"sU2Wk","\"\u002Fusr\"",[117,198,199],{"class":127},", ",[117,201,202],{"class":171},"True",[117,204,175],{"class":127},[117,206,208],{"class":119,"line":207},9,[117,209,210],{"class":127},"qgs.initQgis()\n",[117,212,214],{"class":119,"line":213},10,[117,215,149],{"emptyLinePlaceholder":148},[117,217,219],{"class":119,"line":218},11,[117,220,221],{"class":155},"# 3. Initialize the Processing framework\n",[117,223,225,228,231],{"class":119,"line":224},12,[117,226,227],{"class":127},"sys.path.append(",[117,229,230],{"class":195},"\"\u002Fusr\u002Fshare\u002Fqgis\u002Fpython\u002Fplugins\"",[117,232,175],{"class":127},[117,234,236,238,241,243],{"class":119,"line":235},13,[117,237,134],{"class":123},[117,239,240],{"class":127}," processing.core.Processing ",[117,242,124],{"class":123},[117,244,245],{"class":127}," Processing\n",[117,247,249],{"class":119,"line":248},14,[117,250,251],{"class":127},"Processing.initialize()\n",[117,253,255],{"class":119,"line":254},15,[117,256,149],{"emptyLinePlaceholder":148},[117,258,260],{"class":119,"line":259},16,[117,261,262],{"class":155},"# 4. Register the native (C++) algorithm provider\n",[117,264,266,268,271,273],{"class":119,"line":265},17,[117,267,134],{"class":123},[117,269,270],{"class":127}," qgis.analysis ",[117,272,124],{"class":123},[117,274,275],{"class":127}," QgsNativeAlgorithms\n",[117,277,279],{"class":119,"line":278},18,[117,280,281],{"class":127},"QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())\n",[14,283,284,287,288,291,292,295,296,299,300,303,304,307,308,311,312,315,316,319,320,323,324,326,327,329,330,333],{},[23,285,286],{},"Breakdown:"," ",[18,289,290],{},"QgsApplication([], False)"," starts QGIS without a GUI event loop. ",[18,293,294],{},"setPrefixPath"," tells QGIS where its resources live — ",[18,297,298],{},"\u002Fusr"," is typical on Debian\u002FUbuntu; on Windows it is your OSGeo4W ",[18,301,302],{},"apps\u002Fqgis"," (or ",[18,305,306],{},"qgis-ltr",") folder. The plugins directory must be on ",[18,309,310],{},"sys.path"," before importing ",[18,313,314],{},"Processing",". ",[18,317,318],{},"Processing.initialize()"," loads the GDAL\u002FSAGA\u002FGRASS providers, and ",[18,321,322],{},"addProvider(QgsNativeAlgorithms())"," adds the ",[18,325,105],{}," set that ",[18,328,318],{}," does not register on its own — skip this step and ",[18,331,332],{},"native:buffer"," and friends will be reported as unknown.",[49,335,337],{"id":336},"discover-an-algorithms-parameters","Discover an Algorithm's Parameters",[14,339,340,341,344],{},"You should never guess parameter names. ",[18,342,343],{},"processing.algorithmHelp(\"provider:name\")"," prints the full signature: every input, its type, acceptable values, and the output names.",[108,346,348],{"className":110,"code":347,"language":112,"meta":113,"style":113},"import processing\n\nprocessing.algorithmHelp(\"native:buffer\")\n",[18,349,350,357,361],{"__ignoreMap":113},[117,351,352,354],{"class":119,"line":120},[117,353,124],{"class":123},[117,355,356],{"class":127}," processing\n",[117,358,359],{"class":119,"line":131},[117,360,149],{"emptyLinePlaceholder":148},[117,362,363,366,369],{"class":119,"line":145},[117,364,365],{"class":127},"processing.algorithmHelp(",[117,367,368],{"class":195},"\"native:buffer\"",[117,370,175],{"class":127},[14,372,373,375,376,199,379,199,382,199,385,199,388,391,392,394,395,398,399,40],{},[23,374,286],{}," This prints each parameter with its internal key (e.g. ",[18,377,378],{},"INPUT",[18,380,381],{},"DISTANCE",[18,383,384],{},"SEGMENTS",[18,386,387],{},"DISSOLVE",[18,389,390],{},"OUTPUT",") and the expected value type. Those keys are exactly what you put in the parameters dictionary for ",[18,393,33],{},". To list every available algorithm ID instead, iterate ",[18,396,397],{},"QgsApplication.processingRegistry().algorithms()"," and print each ",[18,400,401],{},"alg.id()",[49,403,405],{"id":404},"run-the-algorithm-and-read-output","Run the Algorithm and Read OUTPUT",[14,407,408,409,412,413,415],{},"With parameters known, call ",[18,410,411],{},"processing.run(algorithm_id, params)",". It returns a dictionary; the geometry\u002Ffile result is almost always under the ",[18,414,390],{}," key.",[108,417,419],{"className":110,"code":418,"language":112,"meta":113,"style":113},"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",[18,420,421,427,431,441,455,471,483,494,506,511,515,530,534,553],{"__ignoreMap":113},[117,422,423,425],{"class":119,"line":120},[117,424,124],{"class":123},[117,426,356],{"class":127},[117,428,429],{"class":119,"line":131},[117,430,149],{"emptyLinePlaceholder":148},[117,432,433,436,438],{"class":119,"line":145},[117,434,435],{"class":127},"params ",[117,437,165],{"class":123},[117,439,440],{"class":127}," {\n",[117,442,443,446,449,452],{"class":119,"line":152},[117,444,445],{"class":195},"    \"INPUT\"",[117,447,448],{"class":127},": ",[117,450,451],{"class":195},"\"\u002Fdata\u002Fpoints.gpkg\"",[117,453,454],{"class":127},",\n",[117,456,457,460,462,465,468],{"class":119,"line":159},[117,458,459],{"class":195},"    \"DISTANCE\"",[117,461,448],{"class":127},[117,463,464],{"class":171},"250",[117,466,467],{"class":127},",            ",[117,469,470],{"class":155},"# in the layer's CRS units\n",[117,472,473,476,478,481],{"class":119,"line":178},[117,474,475],{"class":195},"    \"SEGMENTS\"",[117,477,448],{"class":127},[117,479,480],{"class":171},"8",[117,482,454],{"class":127},[117,484,485,488,490,492],{"class":119,"line":183},[117,486,487],{"class":195},"    \"DISSOLVE\"",[117,489,448],{"class":127},[117,491,172],{"class":171},[117,493,454],{"class":127},[117,495,496,499,501,504],{"class":119,"line":189},[117,497,498],{"class":195},"    \"OUTPUT\"",[117,500,448],{"class":127},[117,502,503],{"class":195},"\"\u002Fdata\u002Foutput\u002Fpoints_buffered.gpkg\"",[117,505,454],{"class":127},[117,507,508],{"class":119,"line":207},[117,509,510],{"class":127},"}\n",[117,512,513],{"class":119,"line":213},[117,514,149],{"emptyLinePlaceholder":148},[117,516,517,520,522,525,527],{"class":119,"line":218},[117,518,519],{"class":127},"result ",[117,521,165],{"class":123},[117,523,524],{"class":127}," processing.run(",[117,526,368],{"class":195},[117,528,529],{"class":127},", params)\n",[117,531,532],{"class":119,"line":224},[117,533,149],{"emptyLinePlaceholder":148},[117,535,536,539,542,545,547,550],{"class":119,"line":235},[117,537,538],{"class":171},"print",[117,540,541],{"class":127},"(",[117,543,544],{"class":195},"\"Result keys:\"",[117,546,199],{"class":127},[117,548,549],{"class":171},"list",[117,551,552],{"class":127},"(result.keys()))\n",[117,554,555,557,559,562,565,568],{"class":119,"line":248},[117,556,538],{"class":171},[117,558,541],{"class":127},[117,560,561],{"class":195},"\"Output written to:\"",[117,563,564],{"class":127},", result[",[117,566,567],{"class":195},"\"OUTPUT\"",[117,569,570],{"class":127},"])\n",[14,572,573,287,575,577,578,580,581,584,585,588,589,592],{},[23,574,286],{},[18,576,33],{}," executes synchronously and returns a dict keyed by the algorithm's output names. When ",[18,579,390],{}," was a file path, ",[18,582,583],{},"result[\"OUTPUT\"]"," is that path string; when it was ",[18,586,587],{},"TEMPORARY_OUTPUT",", it is an in-memory layer reference. Inspecting ",[18,590,591],{},"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,594,595],{},"To use the result immediately, load it as a layer:",[108,597,599],{"className":110,"code":598,"language":112,"meta":113,"style":113},"from qgis.core import QgsVectorLayer\n\nout_layer = QgsVectorLayer(result[\"OUTPUT\"], \"buffered\", \"ogr\")\nprint(\"Feature count:\", out_layer.featureCount())\n",[18,600,601,612,616,641],{"__ignoreMap":113},[117,602,603,605,607,609],{"class":119,"line":120},[117,604,134],{"class":123},[117,606,137],{"class":127},[117,608,124],{"class":123},[117,610,611],{"class":127}," QgsVectorLayer\n",[117,613,614],{"class":119,"line":131},[117,615,149],{"emptyLinePlaceholder":148},[117,617,618,621,623,626,628,631,634,636,639],{"class":119,"line":145},[117,619,620],{"class":127},"out_layer ",[117,622,165],{"class":123},[117,624,625],{"class":127}," QgsVectorLayer(result[",[117,627,567],{"class":195},[117,629,630],{"class":127},"], ",[117,632,633],{"class":195},"\"buffered\"",[117,635,199],{"class":127},[117,637,638],{"class":195},"\"ogr\"",[117,640,175],{"class":127},[117,642,643,645,647,650],{"class":119,"line":152},[117,644,538],{"class":171},[117,646,541],{"class":127},[117,648,649],{"class":195},"\"Feature count:\"",[117,651,652],{"class":127},", out_layer.featureCount())\n",[14,654,655,657,658,661,662,664,665,667,668,672,673,675,676,40],{},[23,656,286],{}," A file-path output is opened with the ",[18,659,660],{},"ogr"," provider. A ",[18,663,587],{}," result is already a layer object and needs no reloading — assign ",[18,666,583],{}," directly. This is the same dictionary pattern used when ",[36,669,671],{"href":670},"\u002Fspatial-data-processing-automation\u002Fchaining-processing-algorithms\u002Fchain-buffer-and-clip-pyqgis\u002F","chaining processing algorithms",", where one step's ",[18,674,390],{}," feeds the next step's ",[18,677,378],{},[49,679,681],{"id":680},"a-complete-runnable-script","A Complete Runnable Script",[14,683,684,685,688],{},"Putting the pieces together, including a clean shutdown with ",[18,686,687],{},"exitQgis()",":",[108,690,692],{"className":110,"code":691,"language":112,"meta":113,"style":113},"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",[18,693,694,700,711,715,727,739,743,747,755,765,771,781,785,789,793,797,805,819,830,842,854,866,878,884,906,934,942],{"__ignoreMap":113},[117,695,696,698],{"class":119,"line":120},[117,697,124],{"class":123},[117,699,128],{"class":127},[117,701,702,704,706,708],{"class":119,"line":131},[117,703,134],{"class":123},[117,705,137],{"class":127},[117,707,124],{"class":123},[117,709,710],{"class":127}," QgsApplication, QgsVectorLayer\n",[117,712,713],{"class":119,"line":145},[117,714,149],{"emptyLinePlaceholder":148},[117,716,717,719,721,723,725],{"class":119,"line":152},[117,718,162],{"class":127},[117,720,165],{"class":123},[117,722,168],{"class":127},[117,724,172],{"class":171},[117,726,175],{"class":127},[117,728,729,731,733,735,737],{"class":119,"line":159},[117,730,192],{"class":127},[117,732,196],{"class":195},[117,734,199],{"class":127},[117,736,202],{"class":171},[117,738,175],{"class":127},[117,740,741],{"class":119,"line":178},[117,742,210],{"class":127},[117,744,745],{"class":119,"line":183},[117,746,149],{"emptyLinePlaceholder":148},[117,748,749,751,753],{"class":119,"line":189},[117,750,227],{"class":127},[117,752,230],{"class":195},[117,754,175],{"class":127},[117,756,757,759,761,763],{"class":119,"line":207},[117,758,134],{"class":123},[117,760,240],{"class":127},[117,762,124],{"class":123},[117,764,245],{"class":127},[117,766,767,769],{"class":119,"line":213},[117,768,124],{"class":123},[117,770,356],{"class":127},[117,772,773,775,777,779],{"class":119,"line":218},[117,774,134],{"class":123},[117,776,270],{"class":127},[117,778,124],{"class":123},[117,780,275],{"class":127},[117,782,783],{"class":119,"line":224},[117,784,149],{"emptyLinePlaceholder":148},[117,786,787],{"class":119,"line":235},[117,788,251],{"class":127},[117,790,791],{"class":119,"line":248},[117,792,281],{"class":127},[117,794,795],{"class":119,"line":254},[117,796,149],{"emptyLinePlaceholder":148},[117,798,799,802],{"class":119,"line":259},[117,800,801],{"class":123},"try",[117,803,804],{"class":127},":\n",[117,806,807,810,812,814,816],{"class":119,"line":265},[117,808,809],{"class":127},"    result ",[117,811,165],{"class":123},[117,813,524],{"class":127},[117,815,368],{"class":195},[117,817,818],{"class":127},", {\n",[117,820,821,824,826,828],{"class":119,"line":278},[117,822,823],{"class":195},"        \"INPUT\"",[117,825,448],{"class":127},[117,827,451],{"class":195},[117,829,454],{"class":127},[117,831,833,836,838,840],{"class":119,"line":832},19,[117,834,835],{"class":195},"        \"DISTANCE\"",[117,837,448],{"class":127},[117,839,464],{"class":171},[117,841,454],{"class":127},[117,843,845,848,850,852],{"class":119,"line":844},20,[117,846,847],{"class":195},"        \"SEGMENTS\"",[117,849,448],{"class":127},[117,851,480],{"class":171},[117,853,454],{"class":127},[117,855,857,860,862,864],{"class":119,"line":856},21,[117,858,859],{"class":195},"        \"DISSOLVE\"",[117,861,448],{"class":127},[117,863,172],{"class":171},[117,865,454],{"class":127},[117,867,869,872,874,876],{"class":119,"line":868},22,[117,870,871],{"class":195},"        \"OUTPUT\"",[117,873,448],{"class":127},[117,875,503],{"class":195},[117,877,454],{"class":127},[117,879,881],{"class":119,"line":880},23,[117,882,883],{"class":127},"    })\n",[117,885,887,890,892,894,896,898,900,902,904],{"class":119,"line":886},24,[117,888,889],{"class":127},"    layer ",[117,891,165],{"class":123},[117,893,625],{"class":127},[117,895,567],{"class":195},[117,897,630],{"class":127},[117,899,633],{"class":195},[117,901,199],{"class":127},[117,903,638],{"class":195},[117,905,175],{"class":127},[117,907,909,912,914,917,920,923,926,929,932],{"class":119,"line":908},25,[117,910,911],{"class":171},"    print",[117,913,541],{"class":127},[117,915,916],{"class":123},"f",[117,918,919],{"class":195},"\"Done: ",[117,921,922],{"class":171},"{",[117,924,925],{"class":127},"layer.featureCount()",[117,927,928],{"class":171},"}",[117,930,931],{"class":195}," features\"",[117,933,175],{"class":127},[117,935,937,940],{"class":119,"line":936},26,[117,938,939],{"class":123},"finally",[117,941,804],{"class":127},[117,943,945],{"class":119,"line":944},27,[117,946,947],{"class":127},"    qgs.exitQgis()\n",[14,949,950,952,953,956,957,959,960,962],{},[23,951,286],{}," The ",[18,954,955],{},"try\u002Ffinally"," guarantees ",[18,958,687],{}," runs even if the algorithm raises, releasing QGIS resources and flushing any open data sources. Omitting ",[18,961,687],{}," can leave file locks or incomplete writes in long-running batch jobs. This skeleton is the template every standalone Processing script should follow.",[49,964,966],{"id":965},"run-algorithms-in-a-batch-loop","Run Algorithms in a Batch Loop",[14,968,969,970,972],{},"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 ",[18,971,33],{}," in a loop over a folder of files, collecting outputs and logging failures so one bad file does not abort the run:",[108,974,976],{"className":110,"code":975,"language":112,"meta":113,"style":113},"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",[18,977,978,990,996,1000,1015,1029,1053,1057,1067,1090,1119,1126,1135,1148,1159,1170,1181,1193,1198,1203,1217,1227,1231,1264,1276],{"__ignoreMap":113},[117,979,980,982,985,987],{"class":119,"line":120},[117,981,134],{"class":123},[117,983,984],{"class":127}," pathlib ",[117,986,124],{"class":123},[117,988,989],{"class":127}," Path\n",[117,991,992,994],{"class":119,"line":131},[117,993,124],{"class":123},[117,995,356],{"class":127},[117,997,998],{"class":119,"line":145},[117,999,149],{"emptyLinePlaceholder":148},[117,1001,1002,1005,1007,1010,1013],{"class":119,"line":152},[117,1003,1004],{"class":127},"source_dir ",[117,1006,165],{"class":123},[117,1008,1009],{"class":127}," Path(",[117,1011,1012],{"class":195},"\"\u002Fdata\u002Fpoints\"",[117,1014,175],{"class":127},[117,1016,1017,1020,1022,1024,1027],{"class":119,"line":159},[117,1018,1019],{"class":127},"output_dir ",[117,1021,165],{"class":123},[117,1023,1009],{"class":127},[117,1025,1026],{"class":195},"\"\u002Fdata\u002Foutput\"",[117,1028,175],{"class":127},[117,1030,1031,1034,1038,1040,1042,1044,1047,1049,1051],{"class":119,"line":178},[117,1032,1033],{"class":127},"output_dir.mkdir(",[117,1035,1037],{"class":1036},"s9osk","parents",[117,1039,165],{"class":123},[117,1041,202],{"class":171},[117,1043,199],{"class":127},[117,1045,1046],{"class":1036},"exist_ok",[117,1048,165],{"class":123},[117,1050,202],{"class":171},[117,1052,175],{"class":127},[117,1054,1055],{"class":119,"line":183},[117,1056,149],{"emptyLinePlaceholder":148},[117,1058,1059,1062,1064],{"class":119,"line":189},[117,1060,1061],{"class":127},"results, errors ",[117,1063,165],{"class":123},[117,1065,1066],{"class":127}," [], []\n",[117,1068,1069,1072,1075,1078,1081,1084,1087],{"class":119,"line":207},[117,1070,1071],{"class":123},"for",[117,1073,1074],{"class":127}," src ",[117,1076,1077],{"class":123},"in",[117,1079,1080],{"class":171}," sorted",[117,1082,1083],{"class":127},"(source_dir.glob(",[117,1085,1086],{"class":195},"\"*.gpkg\"",[117,1088,1089],{"class":127},")):\n",[117,1091,1092,1095,1097,1100,1103,1106,1109,1111,1114,1116],{"class":119,"line":213},[117,1093,1094],{"class":127},"    out_path ",[117,1096,165],{"class":123},[117,1098,1099],{"class":127}," output_dir ",[117,1101,1102],{"class":123},"\u002F",[117,1104,1105],{"class":123}," f",[117,1107,1108],{"class":195},"\"",[117,1110,922],{"class":171},[117,1112,1113],{"class":127},"src.stem",[117,1115,928],{"class":171},[117,1117,1118],{"class":195},"_buffered.gpkg\"\n",[117,1120,1121,1124],{"class":119,"line":218},[117,1122,1123],{"class":123},"    try",[117,1125,804],{"class":127},[117,1127,1128,1131,1133],{"class":119,"line":224},[117,1129,1130],{"class":127},"        processing.run(",[117,1132,368],{"class":195},[117,1134,818],{"class":127},[117,1136,1137,1140,1142,1145],{"class":119,"line":235},[117,1138,1139],{"class":195},"            \"INPUT\"",[117,1141,448],{"class":127},[117,1143,1144],{"class":171},"str",[117,1146,1147],{"class":127},"(src),\n",[117,1149,1150,1153,1155,1157],{"class":119,"line":248},[117,1151,1152],{"class":195},"            \"DISTANCE\"",[117,1154,448],{"class":127},[117,1156,464],{"class":171},[117,1158,454],{"class":127},[117,1160,1161,1164,1166,1168],{"class":119,"line":254},[117,1162,1163],{"class":195},"            \"SEGMENTS\"",[117,1165,448],{"class":127},[117,1167,480],{"class":171},[117,1169,454],{"class":127},[117,1171,1172,1175,1177,1179],{"class":119,"line":259},[117,1173,1174],{"class":195},"            \"DISSOLVE\"",[117,1176,448],{"class":127},[117,1178,172],{"class":171},[117,1180,454],{"class":127},[117,1182,1183,1186,1188,1190],{"class":119,"line":265},[117,1184,1185],{"class":195},"            \"OUTPUT\"",[117,1187,448],{"class":127},[117,1189,1144],{"class":171},[117,1191,1192],{"class":127},"(out_path),\n",[117,1194,1195],{"class":119,"line":278},[117,1196,1197],{"class":127},"        })\n",[117,1199,1200],{"class":119,"line":832},[117,1201,1202],{"class":127},"        results.append(out_path)\n",[117,1204,1205,1208,1211,1214],{"class":119,"line":844},[117,1206,1207],{"class":123},"    except",[117,1209,1210],{"class":171}," Exception",[117,1212,1213],{"class":123}," as",[117,1215,1216],{"class":127}," exc:\n",[117,1218,1219,1222,1224],{"class":119,"line":856},[117,1220,1221],{"class":127},"        errors.append((src.name, ",[117,1223,1144],{"class":171},[117,1225,1226],{"class":127},"(exc)))\n",[117,1228,1229],{"class":119,"line":868},[117,1230,149],{"emptyLinePlaceholder":148},[117,1232,1233,1235,1237,1239,1242,1245,1248,1250,1253,1255,1258,1260,1262],{"class":119,"line":880},[117,1234,538],{"class":171},[117,1236,541],{"class":127},[117,1238,916],{"class":123},[117,1240,1241],{"class":195},"\"Succeeded: ",[117,1243,1244],{"class":171},"{len",[117,1246,1247],{"class":127},"(results)",[117,1249,928],{"class":171},[117,1251,1252],{"class":195},"  Failed: ",[117,1254,1244],{"class":171},[117,1256,1257],{"class":127},"(errors)",[117,1259,928],{"class":171},[117,1261,1108],{"class":195},[117,1263,175],{"class":127},[117,1265,1266,1268,1271,1273],{"class":119,"line":886},[117,1267,1071],{"class":123},[117,1269,1270],{"class":127}," name, msg ",[117,1272,1077],{"class":123},[117,1274,1275],{"class":127}," errors:\n",[117,1277,1278,1280,1282,1284,1287,1289,1292,1294,1296,1298,1301,1303,1305],{"class":119,"line":908},[117,1279,911],{"class":171},[117,1281,541],{"class":127},[117,1283,916],{"class":123},[117,1285,1286],{"class":195},"\"  ",[117,1288,922],{"class":171},[117,1290,1291],{"class":127},"name",[117,1293,928],{"class":171},[117,1295,448],{"class":195},[117,1297,922],{"class":171},[117,1299,1300],{"class":127},"msg",[117,1302,928],{"class":171},[117,1304,1108],{"class":195},[117,1306,175],{"class":127},[14,1308,1309,287,1311,1314,1315,1318,1319,1321,1322,1324,1325,40],{},[23,1310,286],{},[18,1312,1313],{},"Path.glob(\"*.gpkg\")"," enumerates inputs; the ",[18,1316,1317],{},"try\u002Fexcept"," around each ",[18,1320,33],{}," isolates per-file failures so the loop continues and reports them at the end. Building output names from ",[18,1323,1113],{}," keeps results traceable to their source. This is the standalone-script counterpart to the interactive Console patterns covered across ",[36,1326,39],{"href":38},[49,1328,1330],{"id":1329},"capture-progress-and-feedback","Capture Progress and Feedback",[14,1332,1333,1334,1337,1338,1340],{},"Long batch jobs benefit from a feedback object that surfaces progress and any algorithm warnings. Pass a ",[18,1335,1336],{},"QgsProcessingFeedback"," to ",[18,1339,33],{}," to capture them programmatically:",[108,1342,1344],{"className":110,"code":1343,"language":112,"meta":113,"style":113},"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",[18,1345,1346,1352,1363,1367,1371,1387,1398,1411,1415,1431,1443,1447,1451,1460,1467,1472,1482,1492,1502,1512,1522,1527,1537],{"__ignoreMap":113},[117,1347,1348,1350],{"class":119,"line":120},[117,1349,124],{"class":123},[117,1351,356],{"class":127},[117,1353,1354,1356,1358,1360],{"class":119,"line":131},[117,1355,134],{"class":123},[117,1357,137],{"class":127},[117,1359,124],{"class":123},[117,1361,1362],{"class":127}," QgsProcessingFeedback\n",[117,1364,1365],{"class":119,"line":145},[117,1366,149],{"emptyLinePlaceholder":148},[117,1368,1369],{"class":119,"line":152},[117,1370,149],{"emptyLinePlaceholder":148},[117,1372,1373,1376,1380,1382,1384],{"class":119,"line":159},[117,1374,1375],{"class":123},"class",[117,1377,1379],{"class":1378},"svObZ"," LoggingFeedback",[117,1381,541],{"class":127},[117,1383,1336],{"class":1378},[117,1385,1386],{"class":127},"):\n",[117,1388,1389,1392,1395],{"class":119,"line":178},[117,1390,1391],{"class":123},"    def",[117,1393,1394],{"class":1378}," pushInfo",[117,1396,1397],{"class":127},"(self, info):\n",[117,1399,1400,1403,1405,1408],{"class":119,"line":183},[117,1401,1402],{"class":171},"        print",[117,1404,541],{"class":127},[117,1406,1407],{"class":195},"\"INFO:\"",[117,1409,1410],{"class":127},", info)\n",[117,1412,1413],{"class":119,"line":189},[117,1414,149],{"emptyLinePlaceholder":148},[117,1416,1417,1419,1422,1425,1427,1429],{"class":119,"line":207},[117,1418,1391],{"class":123},[117,1420,1421],{"class":1378}," reportError",[117,1423,1424],{"class":127},"(self, error, fatalError",[117,1426,165],{"class":123},[117,1428,172],{"class":171},[117,1430,1386],{"class":127},[117,1432,1433,1435,1437,1440],{"class":119,"line":213},[117,1434,1402],{"class":171},[117,1436,541],{"class":127},[117,1438,1439],{"class":195},"\"ERROR:\"",[117,1441,1442],{"class":127},", error)\n",[117,1444,1445],{"class":119,"line":218},[117,1446,149],{"emptyLinePlaceholder":148},[117,1448,1449],{"class":119,"line":224},[117,1450,149],{"emptyLinePlaceholder":148},[117,1452,1453,1455,1457],{"class":119,"line":235},[117,1454,519],{"class":127},[117,1456,165],{"class":123},[117,1458,1459],{"class":127}," processing.run(\n",[117,1461,1462,1465],{"class":119,"line":248},[117,1463,1464],{"class":195},"    \"native:buffer\"",[117,1466,454],{"class":127},[117,1468,1469],{"class":119,"line":254},[117,1470,1471],{"class":127},"    {\n",[117,1473,1474,1476,1478,1480],{"class":119,"line":259},[117,1475,823],{"class":195},[117,1477,448],{"class":127},[117,1479,451],{"class":195},[117,1481,454],{"class":127},[117,1483,1484,1486,1488,1490],{"class":119,"line":265},[117,1485,835],{"class":195},[117,1487,448],{"class":127},[117,1489,464],{"class":171},[117,1491,454],{"class":127},[117,1493,1494,1496,1498,1500],{"class":119,"line":278},[117,1495,847],{"class":195},[117,1497,448],{"class":127},[117,1499,480],{"class":171},[117,1501,454],{"class":127},[117,1503,1504,1506,1508,1510],{"class":119,"line":832},[117,1505,859],{"class":195},[117,1507,448],{"class":127},[117,1509,172],{"class":171},[117,1511,454],{"class":127},[117,1513,1514,1516,1518,1520],{"class":119,"line":844},[117,1515,871],{"class":195},[117,1517,448],{"class":127},[117,1519,503],{"class":195},[117,1521,454],{"class":127},[117,1523,1524],{"class":119,"line":856},[117,1525,1526],{"class":127},"    },\n",[117,1528,1529,1532,1534],{"class":119,"line":868},[117,1530,1531],{"class":1036},"    feedback",[117,1533,165],{"class":123},[117,1535,1536],{"class":127},"LoggingFeedback(),\n",[117,1538,1539],{"class":119,"line":880},[117,1540,175],{"class":127},[14,1542,1543,1545,1546,1548,1549,1102,1552,1555,1556,1559,1560,1562],{},[23,1544,286],{}," Subclassing ",[18,1547,1336],{}," and overriding ",[18,1550,1551],{},"pushInfo",[18,1553,1554],{},"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 ",[18,1557,1558],{},"feedback"," keyword is accepted by every ",[18,1561,33],{}," call.",[49,1564,1566],{"id":1565},"qgis-version-compatibility","QGIS Version Compatibility",[14,1568,1569,1570,1573],{},"The code targets ",[23,1571,1572],{},"QGIS 3.34 LTR"," (Python 3.12).",[1575,1576,1577,1593],"table",{},[1578,1579,1580],"thead",{},[1581,1582,1583,1587,1590],"tr",{},[1584,1585,1586],"th",{},"QGIS version",[1584,1588,1589],{},"Python",[1584,1591,1592],{},"Notes",[1594,1595,1596,1613,1624],"tbody",{},[1581,1597,1598,1602,1605],{},[1599,1600,1601],"td",{},"3.28 LTR",[1599,1603,1604],{},"3.9",[1599,1606,1607,1608,1610,1611,40],{},"Identical bootstrap; same ",[18,1609,318],{}," and ",[18,1612,101],{},[1581,1614,1615,1618,1621],{},[1599,1616,1617],{},"3.34 LTR",[1599,1619,1620],{},"3.12",[1599,1622,1623],{},"Baseline for this page.",[1581,1625,1626,1629,1631],{},[1599,1627,1628],{},"3.40 \u002F 3.44",[1599,1630,1620],{},[1599,1632,1633],{},"Same initialization API; algorithm IDs unchanged.",[14,1635,1636,1637,199,1639,199,1642,199,1645,1647],{},"The standalone initialization sequence — ",[18,1638,29],{},[18,1640,1641],{},"initQgis",[18,1643,1644],{},"Processing.initialize",[18,1646,322],{}," — has been stable across the entire 3.x line. Only the prefix path differs per platform and install.",[49,1649,1651],{"id":1650},"troubleshooting","Troubleshooting",[54,1653,1654,1667,1675,1687,1700],{},[57,1655,1656,1661,1662,315,1664,1666],{},[23,1657,1658,40],{},[18,1659,1660],{},"Algorithm native:buffer not found"," You skipped ",[18,1663,322],{},[18,1665,318],{}," alone does not register the native provider.",[57,1668,1669,1674],{},[23,1670,1671,40],{},[18,1672,1673],{},"ModuleNotFoundError: No module named 'qgis'"," You are running system Python. Launch with the QGIS\u002FOSGeo4W Python instead.",[57,1676,1677,1682,1683,311,1685,40],{},[23,1678,1679,40],{},[18,1680,1681],{},"No module named 'processing'"," The plugins path is missing — append it to ",[18,1684,310],{},[18,1686,314],{},[57,1688,1689,287,1694,1696,1697,1699],{},[23,1690,1691,40],{},[18,1692,1693],{},"Application path not initialized",[18,1695,294],{}," points at the wrong directory or ",[18,1698,97],{}," was never called. Verify the prefix matches your install.",[57,1701,1702,1705,1706,1708],{},[23,1703,1704],{},"Output file already exists \u002F is locked."," A previous run left the GeoPackage open. Ensure ",[18,1707,687],{}," ran, or write to a fresh path.",[49,1710,1712],{"id":1711},"conclusion","Conclusion",[14,1714,1715,1716,1718,1719,1721,1722,1724,1725,1727,1728,1730,1731,1733,1734,1736],{},"Running a Processing algorithm from a standalone script is straightforward once the bootstrap is correct: start a headless ",[18,1717,29],{},", initialize Processing, and explicitly register ",[18,1720,101],{},". From there, ",[18,1723,46],{}," reveals exact parameter names, ",[18,1726,33],{}," executes the algorithm, and the returned dictionary's ",[18,1729,390],{}," key gives you the result to load or chain. Wrap it in ",[18,1732,955],{}," with ",[18,1735,687],{}," and you have a reliable, GUI-free pattern ready for batch jobs, schedulers, and CI.",[49,1738,1740],{"id":1739},"frequently-asked-questions","Frequently Asked Questions",[14,1742,1743,1746,1747,94,1749,1751,1752,1754],{},[23,1744,1745],{},"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 ",[18,1748,29],{},[18,1750,1641],{},", run ",[18,1753,318],{},", and add the native provider — before any algorithm call works.",[14,1756,1757,1760,1761,1763,1764,1767],{},[23,1758,1759],{},"How do I find an algorithm's parameter names?","\nCall ",[18,1762,343],{},", for example ",[18,1765,1766],{},"processing.algorithmHelp(\"native:buffer\")",". It prints every parameter key and the expected value type, which map directly to your parameters dictionary.",[14,1769,1770,1777,1778,1102,1781,1784,1785,1787,1788,1790],{},[23,1771,1772,1773,1776],{},"What does result",[117,1774,1775],{},"'OUTPUT'"," contain?","\nIt is the algorithm's primary result: a file-path string if you supplied a path, or an in-memory ",[18,1779,1780],{},"QgsVectorLayer",[18,1782,1783],{},"QgsRasterLayer"," if you used ",[18,1786,587],{},". Check ",[18,1789,591],{}," for any additional outputs.",[14,1792,1793,1796,1797,1799],{},[23,1794,1795],{},"Do I need to call exitQgis()?","\nYes, in standalone scripts. It releases resources and flushes data sources. Wrap the work in ",[18,1798,955],{}," so it runs even when an algorithm raises an exception.",[49,1801,1803],{"id":1802},"related","Related",[54,1805,1806,1810,1815],{},[57,1807,1808],{},[36,1809,39],{"href":38},[57,1811,1812],{},[36,1813,1814],{"href":670},"Chain a Buffer and Clip in PyQGIS",[57,1816,1817],{},[36,1818,1820],{"href":1819},"\u002Fqgis-plugin-development\u002Fprocessing-provider-plugins\u002Fwrite-custom-processing-algorithm-pyqgis\u002F","Write a Custom Processing Algorithm in PyQGIS",[1822,1823,1824],"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 .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}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":113,"searchDepth":131,"depth":131,"links":1826},[1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838],{"id":51,"depth":131,"text":52},{"id":87,"depth":131,"text":88},{"id":336,"depth":131,"text":337},{"id":404,"depth":131,"text":405},{"id":680,"depth":131,"text":681},{"id":965,"depth":131,"text":966},{"id":1329,"depth":131,"text":1330},{"id":1565,"depth":131,"text":1566},{"id":1650,"depth":131,"text":1651},{"id":1711,"depth":131,"text":1712},{"id":1739,"depth":131,"text":1740},{"id":1802,"depth":131,"text":1803},"Run a QGIS Processing algorithm from a standalone PyQGIS script. Initialize QgsApplication and Processing, discover parameters, and read result OUTPUT.","md",{},"\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script",{"title":5,"description":1839},"spatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script\u002Findex","ETRklVruaHvaR4lKMJr2HycYuztBSVL2m6QzKCM7txA",1781792483476]