[{"data":1,"prerenderedAt":777},["ShallowReactive",2],{"doc:\u002Fpyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002Frunning-python-scripts-outside-qgis-desktop":3},{"id":4,"title":5,"body":6,"description":770,"extension":771,"meta":772,"navigation":96,"path":773,"seo":774,"stem":775,"__hash__":776},"docs\u002Fpyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002Frunning-python-scripts-outside-qgis-desktop\u002Findex.md","Running Python Scripts Outside QGIS Desktop",{"type":7,"value":8,"toc":764},"minimark",[9,13,42,56,61,473,477,613,617,646,668,672,675,754,760],[10,11,5],"h1",{"id":12},"running-python-scripts-outside-qgis-desktop",[14,15,16,17,21,22,25,26,29,30,33,34,37,38,41],"p",{},"To run Python scripts outside the QGIS desktop, you must manually bootstrap the PyQGIS environment before importing any ",[18,19,20],"code",{},"qgis"," modules. This requires setting ",[18,23,24],{},"QGIS_PREFIX_PATH",", ",[18,27,28],{},"PATH",", and ",[18,31,32],{},"PYTHONPATH"," to your QGIS installation directory, then calling ",[18,35,36],{},"QgsApplication.initQgis()"," in headless mode (",[18,39,40],{},"False","). This bypasses the GUI while retaining full access to vector\u002Fraster APIs, GDAL\u002FOGR drivers, and the Processing framework.",[14,43,44,45,50,51,55],{},"For reproducible deployments, isolate these dependencies to prevent system-level conflicts. A properly configured ",[46,47,49],"a",{"href":48},"\u002Fpyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002F","Virtual Environments for GIS"," ensures your standalone interpreter resolves QGIS libraries consistently across development and production machines. The foundational mapping between Python interpreters and QGIS binaries is detailed in the ",[46,52,54],{"href":53},"\u002Fpyqgis-fundamentals-environment-setup\u002F","PyQGIS Fundamentals & Environment Setup"," reference, which covers version alignment and dependency resolution.",[57,58,60],"h3",{"id":59},"working-code-snippet","Working Code Snippet",[62,63,68],"pre",{"className":64,"code":65,"language":66,"meta":67,"style":67},"language-python shiki shiki-themes github-dark","import os\nimport sys\n\n# 1. Set QGIS installation root (adjust per OS)\nQGIS_PREFIX = r\"C:\\OSGeo4W\\apps\\qgis\" # Windows OSGeo4W\n# macOS: \"\u002FApplications\u002FQGIS.app\u002FContents\u002FMacOS\"\n# Linux: \"\u002Fusr\"\n\n# 2. Inject environment variables BEFORE importing qgis modules\nos.environ[\"QGIS_PREFIX_PATH\"] = QGIS_PREFIX\nos.environ[\"PATH\"] = os.pathsep.join([os.path.join(QGIS_PREFIX, \"bin\"), os.environ.get(\"PATH\", \"\")])\nos.environ[\"PYTHONPATH\"] = os.pathsep.join([os.path.join(QGIS_PREFIX, \"python\"), os.environ.get(\"PYTHONPATH\", \"\")])\n\n# Prepend to sys.path (required for some installations)\nsys.path.insert(0, os.path.join(QGIS_PREFIX, \"python\"))\n\nfrom qgis.core import QgsApplication, QgsVectorLayer\n\n# 3. Initialize headless QGIS application\nQgsApplication.setPrefixPath(QGIS_PREFIX, True)\nqgs = QgsApplication([], False) # False disables GUI\nqgs.initQgis()\n\n# 4. Execute GIS logic\nlayer = QgsVectorLayer(\"data\u002Froads.shp\", \"roads\", \"ogr\")\nif layer.isValid():\n print(f\"Loaded {layer.featureCount()} features\")\nelse:\n print(\"Layer failed to load. Check path and OGR drivers.\")\n\n# 5. Clean shutdown\nqgs.exitQgis()\n","python","",[18,69,70,83,91,98,105,150,156,162,167,173,191,226,257,262,268,289,294,308,313,319,335,354,360,365,371,397,406,435,444,456,461,467],{"__ignoreMap":67},[71,72,75,79],"span",{"class":73,"line":74},"line",1,[71,76,78],{"class":77},"snl16","import",[71,80,82],{"class":81},"s95oV"," os\n",[71,84,86,88],{"class":73,"line":85},2,[71,87,78],{"class":77},[71,89,90],{"class":81}," sys\n",[71,92,94],{"class":73,"line":93},3,[71,95,97],{"emptyLinePlaceholder":96},true,"\n",[71,99,101],{"class":73,"line":100},4,[71,102,104],{"class":103},"sAwPA","# 1. Set QGIS installation root (adjust per OS)\n",[71,106,108,112,115,118,122,126,130,133,136,139,142,145,147],{"class":73,"line":107},5,[71,109,111],{"class":110},"sDLfK","QGIS_PREFIX",[71,113,114],{"class":77}," =",[71,116,117],{"class":77}," r",[71,119,121],{"class":120},"sU2Wk","\"",[71,123,125],{"class":124},"sns5M","C:",[71,127,129],{"class":128},"sRjNt","\\O",[71,131,132],{"class":124},"SGeo4W",[71,134,135],{"class":128},"\\a",[71,137,138],{"class":124},"pps",[71,140,141],{"class":128},"\\q",[71,143,144],{"class":124},"gis",[71,146,121],{"class":120},[71,148,149],{"class":103}," # Windows OSGeo4W\n",[71,151,153],{"class":73,"line":152},6,[71,154,155],{"class":103},"# macOS: \"\u002FApplications\u002FQGIS.app\u002FContents\u002FMacOS\"\n",[71,157,159],{"class":73,"line":158},7,[71,160,161],{"class":103},"# Linux: \"\u002Fusr\"\n",[71,163,165],{"class":73,"line":164},8,[71,166,97],{"emptyLinePlaceholder":96},[71,168,170],{"class":73,"line":169},9,[71,171,172],{"class":103},"# 2. Inject environment variables BEFORE importing qgis modules\n",[71,174,176,179,182,185,188],{"class":73,"line":175},10,[71,177,178],{"class":81},"os.environ[",[71,180,181],{"class":120},"\"QGIS_PREFIX_PATH\"",[71,183,184],{"class":81},"] ",[71,186,187],{"class":77},"=",[71,189,190],{"class":110}," QGIS_PREFIX\n",[71,192,194,196,199,201,203,206,208,210,213,216,218,220,223],{"class":73,"line":193},11,[71,195,178],{"class":81},[71,197,198],{"class":120},"\"PATH\"",[71,200,184],{"class":81},[71,202,187],{"class":77},[71,204,205],{"class":81}," os.pathsep.join([os.path.join(",[71,207,111],{"class":110},[71,209,25],{"class":81},[71,211,212],{"class":120},"\"bin\"",[71,214,215],{"class":81},"), os.environ.get(",[71,217,198],{"class":120},[71,219,25],{"class":81},[71,221,222],{"class":120},"\"\"",[71,224,225],{"class":81},")])\n",[71,227,229,231,234,236,238,240,242,244,247,249,251,253,255],{"class":73,"line":228},12,[71,230,178],{"class":81},[71,232,233],{"class":120},"\"PYTHONPATH\"",[71,235,184],{"class":81},[71,237,187],{"class":77},[71,239,205],{"class":81},[71,241,111],{"class":110},[71,243,25],{"class":81},[71,245,246],{"class":120},"\"python\"",[71,248,215],{"class":81},[71,250,233],{"class":120},[71,252,25],{"class":81},[71,254,222],{"class":120},[71,256,225],{"class":81},[71,258,260],{"class":73,"line":259},13,[71,261,97],{"emptyLinePlaceholder":96},[71,263,265],{"class":73,"line":264},14,[71,266,267],{"class":103},"# Prepend to sys.path (required for some installations)\n",[71,269,271,274,277,280,282,284,286],{"class":73,"line":270},15,[71,272,273],{"class":81},"sys.path.insert(",[71,275,276],{"class":110},"0",[71,278,279],{"class":81},", os.path.join(",[71,281,111],{"class":110},[71,283,25],{"class":81},[71,285,246],{"class":120},[71,287,288],{"class":81},"))\n",[71,290,292],{"class":73,"line":291},16,[71,293,97],{"emptyLinePlaceholder":96},[71,295,297,300,303,305],{"class":73,"line":296},17,[71,298,299],{"class":77},"from",[71,301,302],{"class":81}," qgis.core ",[71,304,78],{"class":77},[71,306,307],{"class":81}," QgsApplication, QgsVectorLayer\n",[71,309,311],{"class":73,"line":310},18,[71,312,97],{"emptyLinePlaceholder":96},[71,314,316],{"class":73,"line":315},19,[71,317,318],{"class":103},"# 3. Initialize headless QGIS application\n",[71,320,322,325,327,329,332],{"class":73,"line":321},20,[71,323,324],{"class":81},"QgsApplication.setPrefixPath(",[71,326,111],{"class":110},[71,328,25],{"class":81},[71,330,331],{"class":110},"True",[71,333,334],{"class":81},")\n",[71,336,338,341,343,346,348,351],{"class":73,"line":337},21,[71,339,340],{"class":81},"qgs ",[71,342,187],{"class":77},[71,344,345],{"class":81}," QgsApplication([], ",[71,347,40],{"class":110},[71,349,350],{"class":81},") ",[71,352,353],{"class":103},"# False disables GUI\n",[71,355,357],{"class":73,"line":356},22,[71,358,359],{"class":81},"qgs.initQgis()\n",[71,361,363],{"class":73,"line":362},23,[71,364,97],{"emptyLinePlaceholder":96},[71,366,368],{"class":73,"line":367},24,[71,369,370],{"class":103},"# 4. Execute GIS logic\n",[71,372,374,377,379,382,385,387,390,392,395],{"class":73,"line":373},25,[71,375,376],{"class":81},"layer ",[71,378,187],{"class":77},[71,380,381],{"class":81}," QgsVectorLayer(",[71,383,384],{"class":120},"\"data\u002Froads.shp\"",[71,386,25],{"class":81},[71,388,389],{"class":120},"\"roads\"",[71,391,25],{"class":81},[71,393,394],{"class":120},"\"ogr\"",[71,396,334],{"class":81},[71,398,400,403],{"class":73,"line":399},26,[71,401,402],{"class":77},"if",[71,404,405],{"class":81}," layer.isValid():\n",[71,407,409,412,415,418,421,424,427,430,433],{"class":73,"line":408},27,[71,410,411],{"class":110}," print",[71,413,414],{"class":81},"(",[71,416,417],{"class":77},"f",[71,419,420],{"class":120},"\"Loaded ",[71,422,423],{"class":110},"{",[71,425,426],{"class":81},"layer.featureCount()",[71,428,429],{"class":110},"}",[71,431,432],{"class":120}," features\"",[71,434,334],{"class":81},[71,436,438,441],{"class":73,"line":437},28,[71,439,440],{"class":77},"else",[71,442,443],{"class":81},":\n",[71,445,447,449,451,454],{"class":73,"line":446},29,[71,448,411],{"class":110},[71,450,414],{"class":81},[71,452,453],{"class":120},"\"Layer failed to load. Check path and OGR drivers.\"",[71,455,334],{"class":81},[71,457,459],{"class":73,"line":458},30,[71,460,97],{"emptyLinePlaceholder":96},[71,462,464],{"class":73,"line":463},31,[71,465,466],{"class":103},"# 5. Clean shutdown\n",[71,468,470],{"class":73,"line":469},32,[71,471,472],{"class":81},"qgs.exitQgis()\n",[57,474,476],{"id":475},"compatibility-requirements","Compatibility Requirements",[478,479,480,496],"table",{},[481,482,483],"thead",{},[484,485,486,490,493],"tr",{},[487,488,489],"th",{},"Component",[487,491,492],{},"Requirement",[487,494,495],{},"Failure Symptom",[497,498,499,520,539,566,593],"tbody",{},[484,500,501,508,511],{},[502,503,504],"td",{},[505,506,507],"strong",{},"Python Version",[502,509,510],{},"Must exactly match QGIS bundled version (e.g., 3.10 for QGIS 3.34+)",[502,512,513,516,517],{},[18,514,515],{},"ImportError: DLL load failed"," or ",[18,518,519],{},"ModuleNotFoundError: qgis",[484,521,522,527,534],{},[502,523,524],{},[505,525,526],{},"QGIS Major Version",[502,528,529,530,533],{},"Scripts must target the exact installed ",[18,531,532],{},"major.minor"," release",[502,535,536],{},[18,537,538],{},"AttributeError: module 'qgis.core' has no attribute 'QgsApplication'",[484,540,541,546,557],{},[502,542,543],{},[505,544,545],{},"Path Separators",[502,547,548,549,552,553,556],{},"Use ",[18,550,551],{},"os.pathsep"," and ",[18,554,555],{},"os.path.join"," to avoid OS-specific crashes",[502,558,559,562,563],{},[18,560,561],{},"FileNotFoundError"," during ",[18,564,565],{},"setPrefixPath()",[484,567,568,573,587],{},[502,569,570],{},[505,571,572],{},"macOS Bundle",[502,574,575,576,578,579,582,583,586],{},"Point ",[18,577,24],{}," to ",[18,580,581],{},"Contents\u002FMacOS",", not the ",[18,584,585],{},".app"," root",[502,588,589,592],{},[18,590,591],{},"QgsApplication"," initializes but fails to load providers",[484,594,595,600,607],{},[502,596,597],{},[505,598,599],{},"Linux Headless",[502,601,602,603,606],{},"Export ",[18,604,605],{},"QT_QPA_PLATFORM=offscreen"," before execution",[502,608,609,612],{},[18,610,611],{},"qt.qpa.xcb: could not connect to display"," crash",[57,614,616],{"id":615},"execution-integration","Execution & Integration",[618,619,620,630,636],"ol",{},[621,622,623,626,627],"li",{},[505,624,625],{},"Direct CLI:"," ",[18,628,629],{},"python standalone_script.py",[621,631,632,635],{},[505,633,634],{},"Scheduled Tasks\u002FCron:"," Wrap execution in a batch\u002Fshell script that exports environment variables first, then invokes Python.",[621,637,638,641,642,645],{},[505,639,640],{},"Processing Framework:"," To use ",[18,643,644],{},"processing.run()",", register native algorithms after initialization:",[62,647,649],{"className":64,"code":648,"language":66,"meta":67,"style":67},"from qgis.analysis import QgsNativeAlgorithms\nQgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())\n",[18,650,651,663],{"__ignoreMap":67},[71,652,653,655,658,660],{"class":73,"line":74},[71,654,299],{"class":77},[71,656,657],{"class":81}," qgis.analysis ",[71,659,78],{"class":77},[71,661,662],{"class":81}," QgsNativeAlgorithms\n",[71,664,665],{"class":73,"line":85},[71,666,667],{"class":81},"QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())\n",[57,669,671],{"id":670},"troubleshooting-fallbacks","Troubleshooting & Fallbacks",[14,673,674],{},"If initialization fails or crashes silently, apply these diagnostic steps:",[618,676,677,693,706,723,737],{},[621,678,679,682,683,552,686,689,690,692],{},[505,680,681],{},"Verify Path Resolution:"," Print ",[18,684,685],{},"sys.executable",[18,687,688],{},"os.environ[\"QGIS_PREFIX_PATH\"]"," immediately after assignment. A mismatched interpreter is the most common cause of missing ",[18,691,20],{}," modules.",[621,694,695,701,702,705],{},[505,696,548,697,700],{},[18,698,699],{},"qgis_process"," (Recommended):"," QGIS 3.14+ ships with a standalone CLI that auto-configures environments. Run ",[18,703,704],{},"qgis_process run --script=your_script.py"," to bypass manual path injection entirely. This is the most reliable fallback for CI\u002FCD pipelines.",[621,707,708,711,712,714,715,718,719,722],{},[505,709,710],{},"Conda Environment Fallback:"," If system paths are unstable or permissions restrict ",[18,713,28],{}," modification, use ",[18,716,717],{},"conda-forge",": ",[18,720,721],{},"conda create -n qgis-standalone qgis python=3.10",". Activate the environment and run your script. Conda automatically resolves GDAL, PROJ, Qt, and SIP bindings.",[621,724,725,728,729,732,733,736],{},[505,726,727],{},"Enable Debug Logging:"," Add ",[18,730,731],{},"QgsApplication.messageLog().logMessage(\"Init check\", \"Standalone\")"," and run with ",[18,734,735],{},"QGIS_LOG_FILE=debug.log"," to capture silent provider load failures.",[621,738,739,742,743,746,747,749,750,753],{},[505,740,741],{},"GDAL Driver Registration:"," If formats fail to open, explicitly call ",[18,744,745],{},"from osgeo import gdal; gdal.UseExceptions()"," and verify ",[18,748,24],{}," includes the ",[18,751,752],{},"gdalplugins"," directory.",[14,755,756,757,759],{},"Standalone execution removes GUI overhead while preserving the full spatial engine. Always validate environment variables at runtime, match Python versions exactly, and prefer ",[18,758,699],{}," or Conda when manual path mapping proves unstable.",[761,762,763],"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 pre.shiki code .sns5M, html code.shiki .sns5M{--shiki-default:#DBEDFF}html pre.shiki code .sRjNt, html code.shiki .sRjNt{--shiki-default:#85E89D;--shiki-default-font-weight:bold}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);}",{"title":67,"searchDepth":85,"depth":85,"links":765},[766,767,768,769],{"id":59,"depth":93,"text":60},{"id":475,"depth":93,"text":476},{"id":615,"depth":93,"text":616},{"id":670,"depth":93,"text":671},"To run Python scripts outside the QGIS desktop, you must manually bootstrap the PyQGIS environment before importing any qgis modules. This requires setting QGIS_PREFIX_PATH, PATH, and PYTHONPATH to your QGIS installation directory, then calling QgsApplication.initQgis() in headless mode (False). This bypasses the GUI while retaining full access to vector\u002Fraster APIs, GDAL\u002FOGR drivers, and the Processing framework.","md",{},"\u002Fpyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002Frunning-python-scripts-outside-qgis-desktop",{"title":5,"description":770},"pyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002Frunning-python-scripts-outside-qgis-desktop\u002Findex","kMwh9c87sNmK31iKeQD5D0Xw2mAId9LLttzGYarKGS8",1777824788928]