[{"data":1,"prerenderedAt":591},["ShallowReactive",2],{"doc:\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fqgis-python-version-compatibility-guide":3},{"id":4,"title":5,"body":6,"description":584,"extension":585,"meta":586,"navigation":194,"path":587,"seo":588,"stem":589,"__hash__":590},"docs\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fqgis-python-version-compatibility-guide\u002Findex.md","QGIS Python Version Compatibility Guide",{"type":7,"value":8,"toc":577},"minimark",[9,13,31,102,119,124,144,148,159,307,311,319,336,374,414,418,428,436,454,462,499,524,528,573],[10,11,5],"h1",{"id":12},"qgis-python-version-compatibility-guide",[14,15,16,17,21,22,26,27,30],"p",{},"QGIS ships with a strictly version-locked Python interpreter. The bundled Python minor version changes with each major release, and ",[18,19,20],"strong",{},"you cannot safely swap it"," for a system Python, conda environment, or standalone installer without breaking compiled ",[23,24,25],"code",{},"qgis.core"," and ",[23,28,29],{},"qgis.gui"," bindings. Always match external packages to the exact minor version QGIS provides.",[32,33,34,50],"table",{},[35,36,37],"thead",{},[38,39,40,44,47],"tr",{},[41,42,43],"th",{},"QGIS Release Range",[41,45,46],{},"Bundled Python",[41,48,49],{},"Compatibility Notes",[51,52,53,69,80,91],"tbody",{},[38,54,55,59,62],{},[56,57,58],"td",{},"3.16–3.22",[56,60,61],{},"3.9.x",[56,63,64,65,68],{},"Legacy LTR. Requires ",[23,66,67],{},"pip install --ignore-installed",".",[38,70,71,74,77],{},[56,72,73],{},"3.24–3.30",[56,75,76],{},"3.9.x → 3.10.x",[56,78,79],{},"Transition builds. macOS Homebrew may ship mismatched wheels.",[38,81,82,85,88],{},[56,83,84],{},"3.32–3.38",[56,86,87],{},"3.10.x",[56,89,90],{},"Stable baseline. C-extensions must target the 3.10 ABI.",[38,92,93,96,99],{},[56,94,95],{},"3.40+",[56,97,98],{},"3.12.x",[56,100,101],{},"Requires updated C-extensions. PyQt6 migration begins.",[14,103,104,107,108,111,112,111,115,118],{},[18,105,106],{},"Rule of thumb:"," Never assume a Python wheel built for your OS system Python will work inside QGIS. Verify the ABI tag (",[23,109,110],{},"cp39",", ",[23,113,114],{},"cp310",[23,116,117],{},"cp312",") matches the QGIS runtime before installing.",[120,121,123],"h2",{"id":122},"why-version-locking-matters","Why Version Locking Matters",[14,125,126,127,132,133,136,137,140,141,68],{},"The ",[128,129,131],"a",{"href":130},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002F","QGIS API Architecture"," relies on SIP-generated Python bindings compiled against a specific Python ABI and Qt\u002FPyQt version. When Python’s minor version changes, the C-extensions in ",[23,134,135],{},"qgis._core"," become binary-incompatible. Mixing external Python installations with QGIS plugins typically triggers ",[23,138,139],{},"ImportError: DLL load failed"," or ",[23,142,143],{},"ModuleNotFoundError: qgis",[120,145,147],{"id":146},"verify-your-active-environment","Verify Your Active Environment",[14,149,150,151,154,155,158],{},"Run this in the ",[18,152,153],{},"QGIS Python Console"," (",[23,156,157],{},"Plugins > Python Console",") to confirm version alignment:",[160,161,166],"pre",{"className":162,"code":163,"language":164,"meta":165,"style":165},"language-python shiki shiki-themes github-dark","import sys\nimport qgis.core\n\nprint(f\"QGIS Python: {sys.version_info.major}.{sys.version_info.minor}\")\nprint(f\"QGIS Core Path: {qgis.core.__file__}\")\n\nif sys.version_info \u003C (3, 9):\n raise RuntimeError(\"Python \u003C 3.9 is incompatible with QGIS 3.16+\")\n","python","",[23,167,168,181,189,196,237,261,266,291],{"__ignoreMap":165},[169,170,173,177],"span",{"class":171,"line":172},"line",1,[169,174,176],{"class":175},"snl16","import",[169,178,180],{"class":179},"s95oV"," sys\n",[169,182,184,186],{"class":171,"line":183},2,[169,185,176],{"class":175},[169,187,188],{"class":179}," qgis.core\n",[169,190,192],{"class":171,"line":191},3,[169,193,195],{"emptyLinePlaceholder":194},true,"\n",[169,197,199,203,206,209,213,216,219,222,224,226,229,231,234],{"class":171,"line":198},4,[169,200,202],{"class":201},"sDLfK","print",[169,204,205],{"class":179},"(",[169,207,208],{"class":175},"f",[169,210,212],{"class":211},"sU2Wk","\"QGIS Python: ",[169,214,215],{"class":201},"{",[169,217,218],{"class":179},"sys.version_info.major",[169,220,221],{"class":201},"}",[169,223,68],{"class":211},[169,225,215],{"class":201},[169,227,228],{"class":179},"sys.version_info.minor",[169,230,221],{"class":201},[169,232,233],{"class":211},"\"",[169,235,236],{"class":179},")\n",[169,238,240,242,244,246,249,251,254,257,259],{"class":171,"line":239},5,[169,241,202],{"class":201},[169,243,205],{"class":179},[169,245,208],{"class":175},[169,247,248],{"class":211},"\"QGIS Core Path: ",[169,250,215],{"class":201},[169,252,253],{"class":179},"qgis.core.",[169,255,256],{"class":201},"__file__}",[169,258,233],{"class":211},[169,260,236],{"class":179},[169,262,264],{"class":171,"line":263},6,[169,265,195],{"emptyLinePlaceholder":194},[169,267,269,272,275,278,280,283,285,288],{"class":171,"line":268},7,[169,270,271],{"class":175},"if",[169,273,274],{"class":179}," sys.version_info ",[169,276,277],{"class":175},"\u003C",[169,279,154],{"class":179},[169,281,282],{"class":201},"3",[169,284,111],{"class":179},[169,286,287],{"class":201},"9",[169,289,290],{"class":179},"):\n",[169,292,294,297,300,302,305],{"class":171,"line":293},8,[169,295,296],{"class":175}," raise",[169,298,299],{"class":201}," RuntimeError",[169,301,205],{"class":179},[169,303,304],{"class":211},"\"Python \u003C 3.9 is incompatible with QGIS 3.16+\"",[169,306,236],{"class":179},[120,308,310],{"id":309},"safe-dependency-installation","Safe Dependency Installation",[14,312,313,314,318],{},"Follow the ",[128,315,317],{"href":316},"\u002Fpyqgis-fundamentals-environment-setup\u002F","PyQGIS Fundamentals & Environment Setup"," workflow to treat QGIS as a self-contained runtime. Add third-party libraries without breaking bindings:",[320,321,322],"ol",{},[323,324,325,332,333,335],"li",{},[18,326,327,328,331],{},"Use the bundled ",[23,329,330],{},"pip",":"," QGIS 3.22+ includes ",[23,334,330],{}," in the console.",[160,337,339],{"className":162,"code":338,"language":164,"meta":165,"style":165},"import subprocess, sys\nsubprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"requests\"])\n",[23,340,341,348],{"__ignoreMap":165},[169,342,343,345],{"class":171,"line":172},[169,344,176],{"class":175},[169,346,347],{"class":179}," subprocess, sys\n",[169,349,350,353,356,358,361,363,366,368,371],{"class":171,"line":183},[169,351,352],{"class":179},"subprocess.check_call([sys.executable, ",[169,354,355],{"class":211},"\"-m\"",[169,357,111],{"class":179},[169,359,360],{"class":211},"\"pip\"",[169,362,111],{"class":179},[169,364,365],{"class":211},"\"install\"",[169,367,111],{"class":179},[169,369,370],{"class":211},"\"requests\"",[169,372,373],{"class":179},"])\n",[320,375,376,397],{"start":183},[323,377,378,381,382,385,386,111,389,392,393,396],{},[18,379,380],{},"Windows:"," Always run external scripts via ",[23,383,384],{},"python-qgis.bat"," (located in the QGIS install folder). This launcher sets ",[23,387,388],{},"PYTHONHOME",[23,390,391],{},"PYTHONPATH",", and ",[23,394,395],{},"QT_PLUGIN_PATH"," automatically.",[323,398,399,402,403,406,407,410,411,413],{},[18,400,401],{},"Linux\u002FmacOS:"," Invoke ",[23,404,405],{},"qgis --code script.py"," or source the official ",[23,408,409],{},"qgis.sh"," environment script. Never manually export ",[23,412,391],{}," to system directories.",[120,415,417],{"id":416},"recover-from-abi-mismatches","Recover from ABI Mismatches",[14,419,420,421,111,424,427],{},"If you encounter ",[23,422,423],{},"ImportError: cannot import name 'QgsApplication'",[23,425,426],{},"DLL load failed",", or silent crashes after installing packages:",[320,429,430],{},[323,431,432,435],{},[18,433,434],{},"Clear corrupted packages:"," Delete manually copied folders in QGIS’s user profile:",[437,438,439,447],"ul",{},[323,440,441,443,444],{},[18,442,380],{}," ",[23,445,446],{},"%APPDATA%\\QGIS\\QGIS3\\profiles\\default\\python\\",[323,448,449,443,451],{},[18,450,401],{},[23,452,453],{},"~\u002F.local\u002Fshare\u002FQGIS\u002FQGIS3\u002Fprofiles\u002Fdefault\u002Fpython\u002F",[320,455,456],{"start":183},[323,457,458,461],{},[18,459,460],{},"Force reinstall via QGIS pip:"," Open the Python Console and run:",[160,463,465],{"className":162,"code":464,"language":164,"meta":165,"style":165},"import subprocess, sys\nsubprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"--force-reinstall\", \"package_name\"])\n",[23,466,467,473],{"__ignoreMap":165},[169,468,469,471],{"class":171,"line":172},[169,470,176],{"class":175},[169,472,347],{"class":179},[169,474,475,477,479,481,483,485,487,489,492,494,497],{"class":171,"line":183},[169,476,352],{"class":179},[169,478,355],{"class":211},[169,480,111],{"class":179},[169,482,360],{"class":211},[169,484,111],{"class":179},[169,486,365],{"class":211},[169,488,111],{"class":179},[169,490,491],{"class":211},"\"--force-reinstall\"",[169,493,111],{"class":179},[169,495,496],{"class":211},"\"package_name\"",[169,498,373],{"class":179},[320,500,501,507],{"start":191},[323,502,503,506],{},[18,504,505],{},"Use OSGeo4W for geospatial wheels:"," For GDAL, Fiona, or Shapely, install via the OSGeo4W installer. It compiles binaries against the exact Python version and MSVC runtime QGIS expects, preventing C-extension segfaults.",[323,508,509,516,517,26,520,523],{},[18,510,511,512,515],{},"Avoid ",[23,513,514],{},"venv"," for QGIS plugins:"," Copying ",[23,518,519],{},"qgis",[23,521,522],{},"PyQt5"," into a virtual environment only works temporarily and breaks on updates. Reserve external environments for pure data processing (pandas, rasterio) that runs outside the QGIS process.",[120,525,527],{"id":526},"deployment-checklist","Deployment Checklist",[437,529,530,540,551,562],{},[323,531,532,533,443,536,539],{},"✅ Match your plugin’s ",[23,534,535],{},"metadata.txt",[23,537,538],{},"qgis_minimum_version"," to the Python version you tested.",[323,541,542,543,546,547,550],{},"✅ Never hardcode ",[23,544,545],{},"sys.path",". Use ",[23,548,549],{},"os.environ[\"PYTHONPATH\"]"," only when spawning external processes.",[323,552,553,554,557,558,561],{},"✅ Audit C-extensions before upgrading QGIS. Python 3.10+ drops legacy wheel formats and changes ",[23,555,556],{},"str","\u002F",[23,559,560],{},"bytes"," handling.",[323,563,564,565,111,567,392,569,572],{},"✅ Keep ",[23,566,25],{},[23,568,29],{},[23,570,571],{},"qgis.analysis"," imports strictly inside the bundled runtime.",[574,575,576],"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 .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);}",{"title":165,"searchDepth":183,"depth":183,"links":578},[579,580,581,582,583],{"id":122,"depth":183,"text":123},{"id":146,"depth":183,"text":147},{"id":309,"depth":183,"text":310},{"id":416,"depth":183,"text":417},{"id":526,"depth":183,"text":527},"QGIS ships with a strictly version-locked Python interpreter. The bundled Python minor version changes with each major release, and you cannot safely swap it for a system Python, conda environment, or standalone installer without breaking compiled qgis.core and qgis.gui bindings. Always match external packages to the exact minor version QGIS provides.","md",{},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fqgis-python-version-compatibility-guide",{"title":5,"description":584},"pyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fqgis-python-version-compatibility-guide\u002Findex","qheWwspru7cMZfX2dvEH6Pf5lWzxIAfMDzwaHrRxyRM",1777824788921]