[{"data":1,"prerenderedAt":1810},["ShallowReactive",2],{"doc:\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-python-console-basics":3},{"id":4,"title":5,"body":6,"description":1799,"extension":1800,"meta":1801,"navigation":567,"path":1806,"seo":1807,"stem":1808,"__hash__":1809},"docs\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-python-console-basics\u002Findex.md","QGIS Python Console Basics",{"type":7,"value":8,"toc":1784},"minimark",[9,13,28,36,204,209,217,228,232,247,430,437,441,444,518,522,535,849,855,882,887,899,1143,1147,1167,1171,1174,1201,1213,1231,1235,1250,1274,1278,1281,1359,1368,1372,1375,1381,1391,1452,1479,1501,1505,1508,1570,1576,1580,1589,1611,1629,1641,1650,1656,1670,1680,1690,1699,1709,1722,1726,1780],[10,11,5],"h1",{"id":12},"qgis-python-console-basics",[14,15,16,17,22,23,27],"p",{},"The QGIS Python Console serves as the primary interactive gateway for automating geospatial workflows, extending core functionality, and prototyping PyQGIS scripts. It is one of the three ways to run Python covered in the parent ",[18,19,21],"a",{"href":20},"\u002Fpyqgis-fundamentals-environment-setup\u002F","PyQGIS Fundamentals & Environment Setup"," guide, and it is the fastest place to explore the ",[18,24,26],{"href":25},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002F","QGIS API architecture"," hands-on: every class you read about in the docs can be instantiated and inspected live against your own data. Mastering the console provides immediate access to the underlying QGIS API without leaving the desktop environment. This guide walks through the essential prerequisites, operational workflow, tested code patterns, and troubleshooting strategies required to build a reliable foundation for spatial automation.",[14,29,30,31,35],{},"The diagram below traces the loop you repeat constantly in the console: type or load code in the console panel, reach the running application through ",[32,33,34],"code",{},"iface",", read or modify the active project and its layers, run, and read the output before iterating again.",[37,38,43,47,51,58,68,77,85,91,97,101,106,111,115,119,124,128,133,141,145,148,153,157,161,165,181,188,192,196,199],"svg",{"viewBox":39,"role":40,"ariaLabel":41,"xmlns":42},"0 0 760 380","img","Data flow from the QGIS Python Console panel through iface to the active project and layers, then back through run and output","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[44,45,46],"title",{},"QGIS Python Console workflow",[48,49,50],"desc",{},"The console panel and editor send commands to iface, which reaches the active project and its layers; running code produces output that feeds the next iteration.",[52,53],"rect",{"x":54,"y":54,"width":55,"height":56,"fill":57},"0","760","380","#f6f3ea",[52,59],{"x":60,"y":61,"width":62,"height":63,"rx":64,"fill":65,"stroke":66,"style":67},"24","28","220","132","10","#fffdf7","#0f766e","stroke-width:2.5",[69,70,76],"text",{"x":71,"y":72,"style":73,"fill":74,"textAnchor":75},"134","54","text-anchor:middle;font-size:15px;font-weight:bold;font-family:sans-serif","#17211d","middle","Console panel + editor",[52,78],{"x":79,"y":80,"width":81,"height":82,"rx":83,"fill":84},"44","70","180","34","6","#26322d",[69,86,90],{"x":71,"y":87,"style":88,"fill":89,"textAnchor":75},"92","text-anchor:middle;font-size:13px;font-family:monospace","#d9f99d",">>> iface.activeLayer()",[69,92,96],{"x":71,"y":93,"style":94,"fill":95,"textAnchor":75},"128","text-anchor:middle;font-size:12px;font-family:sans-serif","#2f3b35","Shell for one-liners,",[69,98,100],{"x":71,"y":99,"style":94,"fill":95,"textAnchor":75},"144","editor for full scripts",[52,102],{"x":103,"y":79,"width":81,"height":104,"rx":64,"fill":65,"stroke":105,"style":67},"300","100","#2563eb",[69,107,34],{"x":108,"y":109,"style":110,"fill":74,"textAnchor":75},"390","86","text-anchor:middle;font-size:15px;font-weight:bold;font-family:monospace",[69,112,114],{"x":108,"y":113,"style":94,"fill":95,"textAnchor":75},"110","qgis.utils.iface",[69,116,118],{"x":108,"y":117,"style":94,"fill":95,"textAnchor":75},"126","app + canvas + legend",[52,120],{"x":121,"y":61,"width":122,"height":63,"rx":64,"fill":65,"stroke":123,"style":67},"536","200","#15803d",[69,125,127],{"x":126,"y":72,"style":73,"fill":74,"textAnchor":75},"636","Active project",[69,129,132],{"x":126,"y":130,"style":131,"fill":95,"textAnchor":75},"80","text-anchor:middle;font-size:12px;font-family:monospace","QgsProject.instance()",[52,134],{"x":135,"y":136,"width":137,"height":138,"rx":83,"fill":57,"stroke":139,"style":140},"556","96","160","48","#22c55e","stroke-width:2",[69,142,144],{"x":126,"y":143,"style":94,"fill":95,"textAnchor":75},"116","Vector \u002F raster",[69,146,147],{"x":126,"y":63,"style":94,"fill":95,"textAnchor":75},"map layers",[52,149],{"x":81,"y":150,"width":151,"height":109,"rx":64,"fill":65,"stroke":152,"style":67},"248","400","#b45309",[69,154,156],{"x":56,"y":155,"style":73,"fill":74,"textAnchor":75},"278","Run → Output",[69,158,160],{"x":56,"y":159,"style":94,"fill":95,"textAnchor":75},"302","print() results, tracebacks, message bar,",[69,162,164],{"x":56,"y":163,"style":94,"fill":95,"textAnchor":75},"320","then iface.mapCanvas().refresh()",[166,167,168],"defs",{},[169,170,177],"marker",{"id":171,"viewBox":172,"refX":173,"refY":174,"markerWidth":175,"markerHeight":175,"orient":176},"ar","0 0 10 10","9","5","7","auto",[178,179],"path",{"d":180,"fill":95},"M0,0 L10,5 L0,10 z",[182,183],"line",{"x1":184,"y1":185,"x2":186,"y2":185,"stroke":95,"style":187},"244","94","296","stroke-width:2.5;marker-end:url(#ar)",[182,189],{"x1":190,"y1":185,"x2":191,"y2":185,"stroke":95,"style":187},"480","532",[178,193],{"d":194,"stroke":95,"fill":195,"style":187},"M610 160 L560 248","none",[178,197],{"d":198,"stroke":95,"fill":195,"style":187},"M200 248 L150 160",[69,200,203],{"x":56,"y":201,"style":202,"fill":66,"textAnchor":75},"356","text-anchor:middle;font-size:12px;font-style:italic;font-family:sans-serif","Inspect output, then iterate on the next command",[205,206,208],"h2",{"id":207},"prerequisites-and-environment-readiness","Prerequisites and Environment Readiness",[14,210,211,212,216],{},"Before executing spatial scripts, ensure your environment meets baseline requirements. A stable installation of QGIS 3.x is mandatory, as the console relies on the bundled Python interpreter, Qt bindings, and GDAL\u002FOGR libraries. This guide pins its examples to the QGIS 3.34+ LTR series; if you run an older release, cross-check method names against the ",[18,213,215],{"href":214},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fqgis-python-version-compatibility-guide\u002F","QGIS Python version compatibility guide"," before assuming a snippet will run. Familiarity with core Python syntax—variables, control flow, list comprehensions, and object-oriented principles—is expected.",[14,218,219,220,224,225,227],{},"For users managing multiple GIS toolchains or Python versions, isolating dependencies through ",[18,221,223],{"href":222},"\u002Fpyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002F","Virtual Environments for GIS"," prevents package conflicts and ensures reproducible execution contexts. Additionally, reviewing the broader ",[18,226,21],{"href":20}," documentation will clarify how the console integrates with the QGIS Processing framework, plugin architecture, and native data providers.",[205,229,231],{"id":230},"accessing-and-configuring-the-interface","Accessing and Configuring the Interface",[14,233,234,235,238,239,242,243,246],{},"The console is embedded directly within the QGIS interface. Navigate to ",[32,236,237],{},"Plugins > Python Console"," or press ",[32,240,241],{},"Ctrl+Alt+P"," (",[32,244,245],{},"Cmd+Option+P"," on macOS). The interface splits into two primary panels: the interactive shell at the bottom and the script editor above. The annotated layout below shows where each region lives in the docked panel.",[37,248,251,254,257,260,267,273,281,286,289,292,295,298,304,306,309,315,320,323,329,333,337,340,344,347,350,353,357,361,366,370,374,382,387,393,397,400,403,407,411,415,418,422,426],{"viewBox":249,"role":40,"ariaLabel":250,"xmlns":42},"0 0 760 420","Annotated layout of the QGIS Python Console panel showing the toolbar, the script editor pane, and the interactive shell pane",[44,252,253],{},"Anatomy of the QGIS Python Console panel",[48,255,256],{},"The docked console panel has three regions: a toolbar row of run, open-editor, clear and settings buttons; a script editor pane above holding numbered multi-line Python you save as a .py file; and a dark interactive shell pane below where you type one-liners at the triple-chevron prompt and read output instantly.",[52,258],{"x":54,"y":54,"width":55,"height":259,"fill":57},"420",[69,261,266],{"x":262,"y":263,"style":264,"fill":74,"textAnchor":265},"20","30","text-anchor:start;font-family:sans-serif;font-size:16px;font-weight:bold","start","Anatomy of the Python Console panel",[52,268],{"x":269,"y":270,"width":271,"height":272,"rx":64,"fill":65,"stroke":66,"style":67},"40","50","520","352",[52,274],{"x":275,"y":276,"width":277,"height":82,"rx":83,"fill":278,"stroke":279,"style":280},"52","62","496","#f0ebdd","#b0a488","stroke-width:1",[52,282],{"x":276,"y":283,"width":262,"height":262,"rx":284,"fill":65,"stroke":123,"style":285},"69","4","stroke-width:1.5",[178,287],{"d":288,"fill":123},"M69 74 L79 79 L69 84 Z",[52,290],{"x":291,"y":283,"width":262,"height":262,"rx":284,"fill":65,"stroke":66,"style":285},"90",[178,293],{"d":294,"stroke":66,"style":285,"fill":195},"M96 84 L104 74 M100 74 L104 74 L104 78",[52,296],{"x":297,"y":283,"width":262,"height":262,"rx":284,"fill":65,"stroke":152,"style":285},"118",[182,299],{"x1":300,"y1":301,"x2":302,"y2":303,"stroke":152,"style":285},"123","74","133","84",[182,305],{"x1":302,"y1":301,"x2":300,"y2":303,"stroke":152,"style":285},[52,307],{"x":308,"y":283,"width":262,"height":262,"rx":284,"fill":65,"stroke":105,"style":285},"146",[310,311],"circle",{"cx":312,"cy":313,"r":314,"fill":195,"stroke":105,"style":285},"156","79","3.5",[52,316],{"x":275,"y":317,"width":277,"height":318,"rx":83,"fill":319,"stroke":279,"style":285},"106","150","#fbf8f0",[52,321],{"x":275,"y":317,"width":82,"height":318,"rx":83,"fill":322},"#efe9db",[69,324,328],{"x":283,"y":325,"style":326,"fill":327,"textAnchor":75},"140","text-anchor:middle;font-family:monospace;font-size:12px","#625b43","1",[69,330,332],{"x":283,"y":331,"style":326,"fill":327,"textAnchor":75},"168","2",[69,334,336],{"x":283,"y":335,"style":326,"fill":327,"textAnchor":75},"196","3",[69,338,284],{"x":283,"y":339,"style":326,"fill":327,"textAnchor":75},"224",[69,341,343],{"x":136,"y":325,"style":342,"fill":74,"textAnchor":265},"text-anchor:start;font-family:monospace;font-size:12.5px","from qgis.core import QgsProject",[69,345,346],{"x":136,"y":331,"style":342,"fill":74,"textAnchor":265},"layer = iface.activeLayer()",[69,348,349],{"x":136,"y":335,"style":342,"fill":74,"textAnchor":265},"print(layer.name(), layer.featureCount())",[69,351,352],{"x":136,"y":339,"style":342,"fill":327,"textAnchor":265},"# tweak, re-run, repeat",[52,354],{"x":275,"y":355,"width":277,"height":356,"rx":83,"fill":84},"266","124",[69,358,360],{"x":359,"y":186,"style":342,"fill":89,"textAnchor":265},"66",">>> iface.activeLayer().featureCount()",[69,362,365],{"x":359,"y":363,"style":342,"fill":364,"textAnchor":265},"318","#e7e2d4","812",[69,367,369],{"x":359,"y":368,"style":342,"fill":89,"textAnchor":265},"346",">>> layer.name()",[69,371,373],{"x":359,"y":372,"style":342,"fill":364,"textAnchor":265},"368","'municipal_boundaries'",[166,375,376],{},[169,377,379],{"id":378,"viewBox":172,"refX":332,"refY":174,"markerWidth":175,"markerHeight":175,"orient":176},"consoleArrow",[178,380],{"d":381,"fill":95},"M10,0 L0,5 L10,10 z",[182,383],{"x1":384,"y1":313,"x2":385,"y2":313,"stroke":95,"style":386},"576","558","stroke-width:2;marker-end:url(#consoleArrow)",[69,388,392],{"x":389,"y":390,"style":391,"fill":74,"textAnchor":265},"584","76","text-anchor:start;font-family:sans-serif;font-size:13px;font-weight:bold","Toolbar",[69,394,396],{"x":389,"y":87,"style":395,"fill":95,"textAnchor":265},"text-anchor:start;font-family:sans-serif;font-size:12px","run · open editor ·",[69,398,399],{"x":389,"y":317,"style":395,"fill":95,"textAnchor":265},"clear · settings",[182,401],{"x1":384,"y1":402,"x2":385,"y2":402,"stroke":95,"style":386},"181",[69,404,406],{"x":389,"y":405,"style":391,"fill":66,"textAnchor":265},"172","Script editor",[69,408,410],{"x":389,"y":409,"style":395,"fill":95,"textAnchor":265},"188","compose, save & run",[69,412,414],{"x":389,"y":413,"style":395,"fill":95,"textAnchor":265},"202","multi-line .py files",[182,416],{"x1":384,"y1":417,"x2":385,"y2":417,"stroke":95,"style":386},"328",[69,419,421],{"x":389,"y":420,"style":391,"fill":152,"textAnchor":265},"319","Interactive shell",[69,423,425],{"x":389,"y":424,"style":395,"fill":95,"textAnchor":265},"335","run one-liners, read",[69,427,429],{"x":389,"y":428,"style":395,"fill":95,"textAnchor":265},"349","output instantly",[14,431,432,433,436],{},"The shell supports immediate command execution, making it ideal for testing single-line operations, inspecting layer properties, or querying the project state. The script editor allows multi-line code composition, saving ",[32,434,435],{},".py"," files, and executing complete workflows. Toggle the editor visibility using the paper-and-pencil icon in the console toolbar. For improved readability, access the console settings via the gear icon to adjust font size, enable line numbers, and configure auto-completion behavior.",[205,438,440],{"id":439},"core-workflow-for-script-execution","Core Workflow for Script Execution",[14,442,443],{},"A reliable console workflow follows a predictable sequence that minimizes state conflicts and ensures clean resource management:",[445,446,447,466,479,498,508],"ol",{},[448,449,450,454,455,458,459,462,463,465],"li",{},[451,452,453],"strong",{},"Initialize the Environment:"," The console automatically imports ",[32,456,457],{},"qgis.core"," and ",[32,460,461],{},"qgis.gui",". The ",[32,464,34],{}," object is pre-loaded and provides direct access to the QGIS application interface, map canvas, and legend.",[448,467,468,471,472,474,475,478],{},[451,469,470],{},"Reference Active Data:"," Use ",[32,473,132],{}," to interact with the currently open project. Layers can be referenced by name, ID, or loaded dynamically from disk using ",[32,476,477],{},"QgsVectorLayer",".",[448,480,481,484,485,488,489,493,494,497],{},[451,482,483],{},"Execute Operations:"," Apply geoprocessing algorithms, modify symbology, or export data using PyQGIS classes. Algorithms are invoked through ",[32,486,487],{},"processing.run()",", the same entry point you would later call from a script when you ",[18,490,492],{"href":491},"\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script\u002F","run a Processing algorithm from a standalone script",". Always wrap operations in ",[32,495,496],{},"try\u002Fexcept"," blocks to handle missing data gracefully.",[448,499,500,503,504,507],{},[451,501,502],{},"Validate Output:"," Check the console log for success messages, warnings, or tracebacks. Use ",[32,505,506],{},"print()"," statements strategically to monitor variable states during execution.",[448,509,510,513,514,517],{},[451,511,512],{},"Refresh the Canvas:"," After modifying layer properties or adding new features, call ",[32,515,516],{},"iface.mapCanvas().refresh()"," to force a visual update.",[205,519,521],{"id":520},"code-breakdown-foundational-patterns","Code Breakdown: Foundational Patterns",[14,523,524,525,527,528,531,532,534],{},"Understanding how to interact with the QGIS API requires familiarity with three core objects: ",[32,526,34],{},", ",[32,529,530],{},"QgsProject",", and ",[32,533,477],{},". Below is a tested pattern that demonstrates layer iteration, attribute inspection, and safe execution practices.",[536,537,542],"pre",{"className":538,"code":539,"language":540,"meta":541,"style":541},"language-python shiki shiki-themes github-dark","from qgis.core import QgsProject, QgsVectorLayer\n\n# Access the active project instance\nproject = QgsProject.instance()\n\n# Map geometry type integers to readable strings\ngeom_map = {0: 'Point', 1: 'Line', 2: 'Polygon', 3: 'Unknown'}\n\n# Retrieve all loaded vector layers\nfor layer in project.mapLayers().values():\n    if isinstance(layer, QgsVectorLayer):\n        geom_type = geom_map.get(layer.geometryType(), 'Unknown')\n        print(f\"Layer: {layer.name()} | Geometry: {geom_type}\")\n\n        # Count features safely\n        feature_count = layer.featureCount()\n        print(f\"  Features: {feature_count}\")\n\n        # Access the first attribute field name\n        if feature_count > 0 and layer.fields():\n            print(f\"  First Field: {layer.fields()[0].name()}\")\n","python","",[32,543,544,562,569,576,588,593,599,650,655,661,676,688,704,743,748,754,765,788,793,799,820],{"__ignoreMap":541},[545,546,548,552,556,559],"span",{"class":182,"line":547},1,[545,549,551],{"class":550},"snl16","from",[545,553,555],{"class":554},"s95oV"," qgis.core ",[545,557,558],{"class":550},"import",[545,560,561],{"class":554}," QgsProject, QgsVectorLayer\n",[545,563,565],{"class":182,"line":564},2,[545,566,568],{"emptyLinePlaceholder":567},true,"\n",[545,570,572],{"class":182,"line":571},3,[545,573,575],{"class":574},"sjoCn","# Access the active project instance\n",[545,577,579,582,585],{"class":182,"line":578},4,[545,580,581],{"class":554},"project ",[545,583,584],{"class":550},"=",[545,586,587],{"class":554}," QgsProject.instance()\n",[545,589,591],{"class":182,"line":590},5,[545,592,568],{"emptyLinePlaceholder":567},[545,594,596],{"class":182,"line":595},6,[545,597,598],{"class":574},"# Map geometry type integers to readable strings\n",[545,600,602,605,607,610,613,616,620,622,624,626,629,631,633,635,638,640,642,644,647],{"class":182,"line":601},7,[545,603,604],{"class":554},"geom_map ",[545,606,584],{"class":550},[545,608,609],{"class":554}," {",[545,611,54],{"class":612},"sDLfK",[545,614,615],{"class":554},": ",[545,617,619],{"class":618},"sU2Wk","'Point'",[545,621,527],{"class":554},[545,623,328],{"class":612},[545,625,615],{"class":554},[545,627,628],{"class":618},"'Line'",[545,630,527],{"class":554},[545,632,332],{"class":612},[545,634,615],{"class":554},[545,636,637],{"class":618},"'Polygon'",[545,639,527],{"class":554},[545,641,336],{"class":612},[545,643,615],{"class":554},[545,645,646],{"class":618},"'Unknown'",[545,648,649],{"class":554},"}\n",[545,651,653],{"class":182,"line":652},8,[545,654,568],{"emptyLinePlaceholder":567},[545,656,658],{"class":182,"line":657},9,[545,659,660],{"class":574},"# Retrieve all loaded vector layers\n",[545,662,664,667,670,673],{"class":182,"line":663},10,[545,665,666],{"class":550},"for",[545,668,669],{"class":554}," layer ",[545,671,672],{"class":550},"in",[545,674,675],{"class":554}," project.mapLayers().values():\n",[545,677,679,682,685],{"class":182,"line":678},11,[545,680,681],{"class":550},"    if",[545,683,684],{"class":612}," isinstance",[545,686,687],{"class":554},"(layer, QgsVectorLayer):\n",[545,689,691,694,696,699,701],{"class":182,"line":690},12,[545,692,693],{"class":554},"        geom_type ",[545,695,584],{"class":550},[545,697,698],{"class":554}," geom_map.get(layer.geometryType(), ",[545,700,646],{"class":618},[545,702,703],{"class":554},")\n",[545,705,707,710,713,716,719,722,725,728,731,733,736,738,741],{"class":182,"line":706},13,[545,708,709],{"class":612},"        print",[545,711,712],{"class":554},"(",[545,714,715],{"class":550},"f",[545,717,718],{"class":618},"\"Layer: ",[545,720,721],{"class":612},"{",[545,723,724],{"class":554},"layer.name()",[545,726,727],{"class":612},"}",[545,729,730],{"class":618}," | Geometry: ",[545,732,721],{"class":612},[545,734,735],{"class":554},"geom_type",[545,737,727],{"class":612},[545,739,740],{"class":618},"\"",[545,742,703],{"class":554},[545,744,746],{"class":182,"line":745},14,[545,747,568],{"emptyLinePlaceholder":567},[545,749,751],{"class":182,"line":750},15,[545,752,753],{"class":574},"        # Count features safely\n",[545,755,757,760,762],{"class":182,"line":756},16,[545,758,759],{"class":554},"        feature_count ",[545,761,584],{"class":550},[545,763,764],{"class":554}," layer.featureCount()\n",[545,766,768,770,772,774,777,779,782,784,786],{"class":182,"line":767},17,[545,769,709],{"class":612},[545,771,712],{"class":554},[545,773,715],{"class":550},[545,775,776],{"class":618},"\"  Features: ",[545,778,721],{"class":612},[545,780,781],{"class":554},"feature_count",[545,783,727],{"class":612},[545,785,740],{"class":618},[545,787,703],{"class":554},[545,789,791],{"class":182,"line":790},18,[545,792,568],{"emptyLinePlaceholder":567},[545,794,796],{"class":182,"line":795},19,[545,797,798],{"class":574},"        # Access the first attribute field name\n",[545,800,802,805,808,811,814,817],{"class":182,"line":801},20,[545,803,804],{"class":550},"        if",[545,806,807],{"class":554}," feature_count ",[545,809,810],{"class":550},">",[545,812,813],{"class":612}," 0",[545,815,816],{"class":550}," and",[545,818,819],{"class":554}," layer.fields():\n",[545,821,823,826,828,830,833,835,838,840,843,845,847],{"class":182,"line":822},21,[545,824,825],{"class":612},"            print",[545,827,712],{"class":554},[545,829,715],{"class":550},[545,831,832],{"class":618},"\"  First Field: ",[545,834,721],{"class":612},[545,836,837],{"class":554},"layer.fields()[",[545,839,54],{"class":612},[545,841,842],{"class":554},"].name()",[545,844,727],{"class":612},[545,846,740],{"class":618},[545,848,703],{"class":554},[14,850,851],{},[852,853,854],"em",{},"Breakdown:",[856,857,858,863,873],"ul",{},[448,859,860,862],{},[32,861,132],{}," returns a singleton reference to the currently open QGIS project. Modifying this object directly affects the active map canvas and legend.",[448,864,865,868,869,872],{},[32,866,867],{},"project.mapLayers().values()"," returns all loaded layers. Filtering with ",[32,870,871],{},"isinstance(layer, QgsVectorLayer)"," ensures raster or mesh layers do not trigger geometry-related errors.",[448,874,875,878,879,881],{},[32,876,877],{},"layer.fields()"," provides access to the attribute schema. Always check ",[32,880,877],{}," is non-empty before indexing to avoid index out-of-bounds exceptions.",[883,884,886],"h3",{"id":885},"interactive-data-query-and-selection","Interactive Data Query and Selection",[14,888,889,890,894,895,478],{},"The console excels at rapid spatial queries. The following snippet demonstrates how to select features matching a specific condition and export them using the Processing framework. Once you have validated a call like this interactively, the same pattern scales into ",[18,891,893],{"href":892},"\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002F","batch processing with PyQGIS"," and multi-step ",[18,896,898],{"href":897},"\u002Fspatial-data-processing-automation\u002Fchaining-processing-algorithms\u002F","algorithm chains",[536,900,902],{"className":538,"code":901,"language":540,"meta":541,"style":541},"from qgis.core import QgsProject, QgsExpression\nfrom qgis import processing\n\n# Target a specific layer by name\nlayers = QgsProject.instance().mapLayersByName('municipal_boundaries')\nif not layers:\n    raise RuntimeError(\"Layer 'municipal_boundaries' not found in project.\")\ntarget_layer = layers[0]\n\n# Define a selection expression\nexpression_str = '\"population\" > 50000'\n\n# Apply selection\ntarget_layer.selectByExpression(expression_str)\n\n# Verify selection count\nprint(f\"Selected: {target_layer.selectedFeatureCount()} features\")\n\n# Export selected features to a temporary memory layer\nif target_layer.selectedFeatureCount() > 0:\n    result = processing.run('native:extractbyexpression', {\n        'INPUT': target_layer,\n        'EXPRESSION': expression_str,\n        'OUTPUT': 'memory:'\n    })\n    QgsProject.instance().addMapLayer(result['OUTPUT'])\n",[32,903,904,915,927,931,936,950,961,976,991,995,1000,1010,1014,1019,1024,1028,1033,1057,1061,1066,1080,1096,1105,1114,1125,1131],{"__ignoreMap":541},[545,905,906,908,910,912],{"class":182,"line":547},[545,907,551],{"class":550},[545,909,555],{"class":554},[545,911,558],{"class":550},[545,913,914],{"class":554}," QgsProject, QgsExpression\n",[545,916,917,919,922,924],{"class":182,"line":564},[545,918,551],{"class":550},[545,920,921],{"class":554}," qgis ",[545,923,558],{"class":550},[545,925,926],{"class":554}," processing\n",[545,928,929],{"class":182,"line":571},[545,930,568],{"emptyLinePlaceholder":567},[545,932,933],{"class":182,"line":578},[545,934,935],{"class":574},"# Target a specific layer by name\n",[545,937,938,941,943,946,948],{"class":182,"line":590},[545,939,940],{"class":554},"layers ",[545,942,584],{"class":550},[545,944,945],{"class":554}," QgsProject.instance().mapLayersByName(",[545,947,373],{"class":618},[545,949,703],{"class":554},[545,951,952,955,958],{"class":182,"line":595},[545,953,954],{"class":550},"if",[545,956,957],{"class":550}," not",[545,959,960],{"class":554}," layers:\n",[545,962,963,966,969,971,974],{"class":182,"line":601},[545,964,965],{"class":550},"    raise",[545,967,968],{"class":612}," RuntimeError",[545,970,712],{"class":554},[545,972,973],{"class":618},"\"Layer 'municipal_boundaries' not found in project.\"",[545,975,703],{"class":554},[545,977,978,981,983,986,988],{"class":182,"line":652},[545,979,980],{"class":554},"target_layer ",[545,982,584],{"class":550},[545,984,985],{"class":554}," layers[",[545,987,54],{"class":612},[545,989,990],{"class":554},"]\n",[545,992,993],{"class":182,"line":657},[545,994,568],{"emptyLinePlaceholder":567},[545,996,997],{"class":182,"line":663},[545,998,999],{"class":574},"# Define a selection expression\n",[545,1001,1002,1005,1007],{"class":182,"line":678},[545,1003,1004],{"class":554},"expression_str ",[545,1006,584],{"class":550},[545,1008,1009],{"class":618}," '\"population\" > 50000'\n",[545,1011,1012],{"class":182,"line":690},[545,1013,568],{"emptyLinePlaceholder":567},[545,1015,1016],{"class":182,"line":706},[545,1017,1018],{"class":574},"# Apply selection\n",[545,1020,1021],{"class":182,"line":745},[545,1022,1023],{"class":554},"target_layer.selectByExpression(expression_str)\n",[545,1025,1026],{"class":182,"line":750},[545,1027,568],{"emptyLinePlaceholder":567},[545,1029,1030],{"class":182,"line":756},[545,1031,1032],{"class":574},"# Verify selection count\n",[545,1034,1035,1038,1040,1042,1045,1047,1050,1052,1055],{"class":182,"line":767},[545,1036,1037],{"class":612},"print",[545,1039,712],{"class":554},[545,1041,715],{"class":550},[545,1043,1044],{"class":618},"\"Selected: ",[545,1046,721],{"class":612},[545,1048,1049],{"class":554},"target_layer.selectedFeatureCount()",[545,1051,727],{"class":612},[545,1053,1054],{"class":618}," features\"",[545,1056,703],{"class":554},[545,1058,1059],{"class":182,"line":790},[545,1060,568],{"emptyLinePlaceholder":567},[545,1062,1063],{"class":182,"line":795},[545,1064,1065],{"class":574},"# Export selected features to a temporary memory layer\n",[545,1067,1068,1070,1073,1075,1077],{"class":182,"line":801},[545,1069,954],{"class":550},[545,1071,1072],{"class":554}," target_layer.selectedFeatureCount() ",[545,1074,810],{"class":550},[545,1076,813],{"class":612},[545,1078,1079],{"class":554},":\n",[545,1081,1082,1085,1087,1090,1093],{"class":182,"line":822},[545,1083,1084],{"class":554},"    result ",[545,1086,584],{"class":550},[545,1088,1089],{"class":554}," processing.run(",[545,1091,1092],{"class":618},"'native:extractbyexpression'",[545,1094,1095],{"class":554},", {\n",[545,1097,1099,1102],{"class":182,"line":1098},22,[545,1100,1101],{"class":618},"        'INPUT'",[545,1103,1104],{"class":554},": target_layer,\n",[545,1106,1108,1111],{"class":182,"line":1107},23,[545,1109,1110],{"class":618},"        'EXPRESSION'",[545,1112,1113],{"class":554},": expression_str,\n",[545,1115,1117,1120,1122],{"class":182,"line":1116},24,[545,1118,1119],{"class":618},"        'OUTPUT'",[545,1121,615],{"class":554},[545,1123,1124],{"class":618},"'memory:'\n",[545,1126,1128],{"class":182,"line":1127},25,[545,1129,1130],{"class":554},"    })\n",[545,1132,1134,1137,1140],{"class":182,"line":1133},26,[545,1135,1136],{"class":554},"    QgsProject.instance().addMapLayer(result[",[545,1138,1139],{"class":618},"'OUTPUT'",[545,1141,1142],{"class":554},"])\n",[14,1144,1145],{},[852,1146,854],{},[856,1148,1149,1155,1161],{},[448,1150,1151,1154],{},[32,1152,1153],{},"from qgis import processing"," explicitly loads the Processing API, ensuring compatibility across QGIS 3.x environments.",[448,1156,1157,1160],{},[32,1158,1159],{},"selectByExpression()"," modifies the layer's selection state without altering the underlying data source.",[448,1162,1163,1164,1166],{},"The ",[32,1165,487],{}," call leverages the native QGIS Processing Framework, which handles background execution, progress reporting, and memory cleanup automatically.",[205,1168,1170],{"id":1169},"common-errors-and-fixes","Common Errors and Fixes",[14,1172,1173],{},"Beginners frequently encounter environment or API mismatches when transitioning from standalone Python to the embedded console. Addressing these systematically accelerates development velocity.",[14,1175,1176,1182,1183,1186,1187,1191,1192,1196,1197,478],{},[451,1177,1178,1179],{},"Error 1: ",[32,1180,1181],{},"ModuleNotFoundError: No module named 'qgis'","\nThis occurs when attempting to run PyQGIS scripts outside the QGIS environment using a standard Python interpreter. The console bypasses this by injecting the correct ",[32,1184,1185],{},"PYTHONPATH"," automatically. If you require external execution for CI\u002FCD pipelines or standalone applications, follow the platform-specific configuration steps in ",[18,1188,1190],{"href":1189},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-python-console-basics\u002Fhow-to-install-qgis-python-bindings-on-windows\u002F","How to install QGIS Python bindings on Windows",", review the deeper diagnosis in ",[18,1193,1195],{"href":1194},"\u002Fpyqgis-fundamentals-environment-setup\u002Fdebugging-pyqgis-scripts\u002Ffixing-pyqgis-module-import-errors\u002F","fixing PyQGIS module import errors",", and learn the initialization pattern for ",[18,1198,1200],{"href":1199},"\u002Fpyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002Frunning-python-scripts-outside-qgis-desktop\u002F","running Python scripts outside QGIS Desktop",[14,1202,1203,1209,1210,1212],{},[451,1204,1205,1206],{},"Error 2: ",[32,1207,1208],{},"AttributeError: 'QgsVectorLayer' object has no attribute 'selectByExpression'","\nThis typically indicates an outdated QGIS version. The ",[32,1211,1159],{}," method is available in QGIS 3.x. Ensure you are not mixing legacy QGIS 2.x syntax with modern implementations. Always reference the official API documentation for your installed QGIS release.",[14,1214,1215,1218,1219,1222,1223,1225,1226,1230],{},[451,1216,1217],{},"Error 3: Console Freezes During Long Operations","\nThe console runs synchronously on the main UI thread. Heavy processing blocks the interface until completion. To mitigate this, wrap intensive loops in ",[32,1220,1221],{},"QgsTask"," or utilize the Processing Framework's ",[32,1224,487],{}," algorithm, which handles background execution and progress reporting natively. For scripts exceeding 30 seconds, consider migrating to the ",[18,1227,1229],{"href":1228},"\u002Fpyqgis-fundamentals-environment-setup\u002Fsetting-up-pycharm-for-qgis\u002F","Setting Up PyCharm for QGIS"," workflow, where asynchronous debugging and thread management are significantly more robust.",[205,1232,1234],{"id":1233},"debugging-strategies-and-best-practices","Debugging Strategies and Best Practices",[14,1236,1237,1238,1241,1242,1245,1246,478],{},"When scripts fail silently or produce unexpected geometry, enable verbose logging. Insert ",[32,1239,1240],{},"import logging; logging.basicConfig(level=logging.DEBUG)"," at the top of your console session. The ",[32,1243,1244],{},"iface.messageBar().pushMessage()"," method provides user-friendly notifications without interrupting execution flow. For the systematic techniques—reading the Python Error tab, inserting breakpoints, and inspecting live objects—see the dedicated guide on ",[18,1247,1249],{"href":1248},"\u002Fpyqgis-fundamentals-environment-setup\u002Fdebugging-pyqgis-scripts\u002F","debugging PyQGIS scripts",[14,1251,1252,1253,1256,1257,1261,1262,1265,1266,1269,1270,1273],{},"Always clear the console cache between major test runs to prevent variable shadowing. Use the toolbar's clear button or press ",[32,1254,1255],{},"Ctrl+L"," in the shell. When working with ",[18,1258,1260],{"href":1259},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002F","coordinate reference systems",", explicitly define transformations using ",[32,1263,1264],{},"QgsCoordinateTransform"," rather than relying on implicit project settings. Cross-platform path handling remains a frequent pain point; avoid hardcoded directories and leverage ",[32,1267,1268],{},"QgsApplication.qgisSettingsDirPath()"," alongside ",[32,1271,1272],{},"os.path.expanduser()"," to ensure portability.",[205,1275,1277],{"id":1276},"what-the-console-gives-you-for-free","What the Console gives you for free",[14,1279,1280],{},"Opening the Console drops you into a Python session that is already wired into the running application. Three names exist that will not exist in a standalone script, and knowing which they are prevents a whole class of \"it worked in the Console\" surprises.",[14,1282,1283],{},[37,1284,1287,1290,1293,1296,1301,1305,1310,1334,1337,1341],{"viewBox":1285,"role":40,"ariaLabel":1286,"xmlns":42},"0 0 760 250","The three preloaded names in the QGIS Python Console — iface, qgis and the imported core module — against a standalone script where only the core module is available after setup",[44,1288,1289],{},"What the Console preloads that a script does not",[48,1291,1292],{},"In the Console, iface, the qgis package and the core classes are already imported and a QgsApplication is already running. In a standalone script the application must be created manually, the core classes must be imported, and iface does not exist at all because there is no interface to reference.",[52,1294],{"x":54,"y":54,"width":55,"height":1295,"fill":57},"250",[69,1297,1300],{"x":56,"y":1298,"style":1299,"fill":74,"textAnchor":75},"26","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","The Console is a session inside a running QGIS",[52,1302],{"x":1303,"y":1304,"width":201,"height":409,"rx":64,"fill":65,"stroke":123,"style":67},"16","46",[69,1306,1309],{"x":1307,"y":80,"style":1308,"fill":123,"textAnchor":75},"194","text-anchor:middle;font-size:12px;font-weight:bold;font-family:sans-serif","the Python Console",[1311,1312,1314,1318,1322,1326,1330],"g",{"style":1313},"font-size:11.5px;font-family:sans-serif",[69,1315,1317],{"x":79,"y":1316,"fill":95},"102","✓  a QgsApplication is already running",[69,1319,1321],{"x":79,"y":1320,"fill":95},"130","✓  iface — the whole interface",[69,1323,1325],{"x":79,"y":1324,"fill":95},"158","✓  qgis.core already imported",[69,1327,1329],{"x":79,"y":1328,"fill":95},"186","✓  the current project, loaded",[69,1331,1333],{"x":79,"y":1332,"fill":123},"214","everything is live and mutable",[52,1335],{"x":1336,"y":1304,"width":201,"height":409,"rx":64,"fill":65,"stroke":152,"style":67},"388",[69,1338,1340],{"x":1339,"y":80,"style":1308,"fill":152,"textAnchor":75},"566","a standalone script",[1311,1342,1343,1347,1350,1353,1356],{"style":1313},[69,1344,1346],{"x":1345,"y":1316,"fill":95},"416","✗  you construct QgsApplication",[69,1348,1349],{"x":1345,"y":1320,"fill":95},"✗  no iface — there is no interface",[69,1351,1352],{"x":1345,"y":1324,"fill":95},"✗  every import is yours to write",[69,1354,1355],{"x":1345,"y":1328,"fill":95},"✗  no project unless you open one",[69,1357,1358],{"x":1345,"y":1332,"fill":152},"nothing exists until you make it",[14,1360,1361,1362,1364,1365,1367],{},"That difference is the reason a snippet copied out of the Console into a scheduled script fails on its first line. The fix is not to avoid the Console — it is by far the fastest way to explore an API — but to treat ",[32,1363,34],{}," as a Console-only convenience and to reach for ",[32,1366,132],{}," whenever the code might later run elsewhere.",[205,1369,1371],{"id":1370},"working-effectively-in-the-console","Working effectively in the Console",[14,1373,1374],{},"A few habits make the Console considerably more useful than a bare prompt.",[14,1376,1377,1380],{},[451,1378,1379],{},"Use the editor pane, not the prompt, for anything over two lines."," The prompt loses your work as soon as you close QGIS; the editor pane saves to a real file you can put in version control and later turn into a plugin.",[14,1382,1383,1386,1387,1390],{},[451,1384,1385],{},"Interrogate objects rather than searching the documentation."," ",[32,1388,1389],{},"dir(layer)"," lists everything a layer can do, and filtering it is faster than any web search:",[536,1392,1394],{"className":538,"code":1393,"language":540,"meta":541,"style":541},"layer = iface.activeLayer()\nprint([name for name in dir(layer) if \"field\" in name.lower()])\nprint(layer.dataProvider().name())\nhelp(layer.selectByExpression)\n",[32,1395,1396,1406,1437,1444],{"__ignoreMap":541},[545,1397,1398,1401,1403],{"class":182,"line":547},[545,1399,1400],{"class":554},"layer ",[545,1402,584],{"class":550},[545,1404,1405],{"class":554}," iface.activeLayer()\n",[545,1407,1408,1410,1413,1415,1418,1420,1423,1426,1428,1431,1434],{"class":182,"line":564},[545,1409,1037],{"class":612},[545,1411,1412],{"class":554},"([name ",[545,1414,666],{"class":550},[545,1416,1417],{"class":554}," name ",[545,1419,672],{"class":550},[545,1421,1422],{"class":612}," dir",[545,1424,1425],{"class":554},"(layer) ",[545,1427,954],{"class":550},[545,1429,1430],{"class":618}," \"field\"",[545,1432,1433],{"class":550}," in",[545,1435,1436],{"class":554}," name.lower()])\n",[545,1438,1439,1441],{"class":182,"line":571},[545,1440,1037],{"class":612},[545,1442,1443],{"class":554},"(layer.dataProvider().name())\n",[545,1445,1446,1449],{"class":182,"line":578},[545,1447,1448],{"class":612},"help",[545,1450,1451],{"class":554},"(layer.selectByExpression)\n",[14,1453,1454,1456,1457,1460,1461,1464,1465,527,1468,527,1471,1474,1475,1478],{},[451,1455,854],{}," Filtering ",[32,1458,1459],{},"dir()"," by a keyword narrows several hundred method names to the handful relevant to what you are doing. ",[32,1462,1463],{},"dataProvider().name()"," returns the provider key — ",[32,1466,1467],{},"ogr",[32,1469,1470],{},"postgres",[32,1472,1473],{},"memory"," — which explains most capability differences you will run into. ",[32,1476,1477],{},"help()"," prints the docstring including the C++ signature, which is often the quickest way to see what a method's arguments actually are.",[14,1480,1481,1484,1485,1488,1489,1492,1493,1496,1497,1500],{},[451,1482,1483],{},"Print objects rather than assuming."," A ",[32,1486,1487],{},"QgsRectangle"," prints as coordinates, a ",[32,1490,1491],{},"QgsCoordinateReferenceSystem"," prints as a description, and a ",[32,1494,1495],{},"QgsGeometry"," prints as WKT via ",[32,1498,1499],{},"asWkt(precision=2)",". Getting into the habit of printing intermediate values turns a confusing result into an obvious one, and it is exactly what the Console is for.",[205,1502,1504],{"id":1503},"key-takeaways","Key Takeaways",[14,1506,1507],{},"Mastering the QGIS Python Console establishes a direct pipeline between spatial data and programmatic control. Keep these anchors in mind as you move from one-liners to full scripts:",[856,1509,1510,1521,1539,1552,1561],{},[448,1511,1512,1386,1515,1517,1518,1520],{},[451,1513,1514],{},"Open it fast, use both panels.",[32,1516,241],{}," opens the console; the shell is for discovery and inspection, the editor for multi-line scripts you save as ",[32,1519,435],{}," and reuse.",[448,1522,1523,1386,1526,1528,1529,1531,1532,1534,1535,1538],{},[451,1524,1525],{},"Three objects carry most workflows.",[32,1527,34],{}," reaches the live application and canvas, ",[32,1530,132],{}," reaches the open project and its layers, and ",[32,1533,477],{}," \u002F ",[32,1536,1537],{},"QgsRasterLayer"," wrap the data itself.",[448,1540,1541,1386,1544,1547,1548,1551],{},[451,1542,1543],{},"Guard every layer lookup.",[32,1545,1546],{},"mapLayersByName()"," returns a list that can be empty, and ",[32,1549,1550],{},"isinstance()"," filtering keeps raster layers out of vector-only code—both prevent the most common console tracebacks.",[448,1553,1554,1560],{},[451,1555,1556,1557,1559],{},"Reach for ",[32,1558,487],{}," on heavy work."," It runs natively, reports progress, and keeps the synchronous UI thread from freezing on long operations.",[448,1562,1563,1566,1567,1569],{},[451,1564,1565],{},"Refresh and validate."," Call ",[32,1568,516],{}," after edits, and print intermediate state so a failing step is obvious before it compounds.",[14,1571,1572,1573,478],{},"The console remains the most efficient entry point for exploring the QGIS API, validating expressions, and bridging the gap between manual cartography and reproducible spatial analysis. When a prototype stabilizes, graduate it into an IDE by ",[18,1574,1575],{"href":1228},"setting up PyCharm for QGIS development",[205,1577,1579],{"id":1578},"frequently-asked-questions","Frequently Asked Questions",[14,1581,1582,1585,1586,1588],{},[451,1583,1584],{},"What is the difference between the console shell and the script editor?","\nThe shell at the bottom runs code one statement at a time and prints results immediately, which is ideal for inspecting a layer or testing an expression. The editor above lets you compose, save, and run multi-line ",[32,1587,435],{}," files as a unit. Most workflows start in the shell for discovery and graduate to the editor once the logic stabilizes.",[14,1590,1591,1597,1598,1600,1601,1603,1604,1606,1607,1610],{},[451,1592,1593,1594,1596],{},"Why is the ",[32,1595,34],{}," object available in the console but not in my standalone script?","\nThe console pre-loads ",[32,1599,34],{}," because it runs inside the live QGIS application and has a real interface, canvas, and legend to expose. A standalone interpreter has no running GUI, so ",[32,1602,34],{}," does not exist there. Use ",[32,1605,132],{}," and the headless ",[32,1608,1609],{},"QgsApplication"," pattern when scripting outside the desktop.",[14,1612,1613,1616,1617,1620,1621,1624,1625,1628],{},[451,1614,1615],{},"How do I reference a layer that is already loaded in my project?","\nCall ",[32,1618,1619],{},"QgsProject.instance().mapLayersByName('layer_name')",", which returns a list of matching layers, then guard against an empty result before indexing ",[32,1622,1623],{},"[0]",". You can also iterate ",[32,1626,1627],{},"QgsProject.instance().mapLayers().values()"," to walk every loaded layer. Referencing by name keeps scripts readable, while referencing by layer ID is safer when names are duplicated.",[14,1630,1631,1634,1635,1637,1638,1640],{},[451,1632,1633],{},"Why does the QGIS interface freeze when I run a long console operation?","\nThe console executes synchronously on the main UI thread, so any heavy loop blocks the entire interface until it finishes. Move intensive work into ",[32,1636,487],{},", which handles background execution, or wrap it in a ",[32,1639,1221],{}," for asynchronous control. For operations that routinely run longer than 30 seconds, a full IDE workflow gives you better thread management.",[14,1642,1643,1646,1647,1649],{},[451,1644,1645],{},"How do I clear console state between test runs?","\nPress ",[32,1648,1255],{}," in the shell or use the toolbar's clear button to wipe the visible output. Clearing the display does not reset Python variables, so re-import modules or re-run setup cells if you suspect variable shadowing from an earlier run. Starting from a clean session avoids stale references to layers that have since been removed.",[14,1651,1652,1655],{},[451,1653,1654],{},"Why does my Console code stop working after I restart QGIS?","\nThe Console prompt keeps no history of definitions between sessions. Anything worth keeping belongs in the editor pane, which saves to a real file, or in a script placed where the Processing toolbox can find it.",[14,1657,1658,1661,1662,1665,1666,1669],{},[451,1659,1660],{},"Can I run a Console script against a project that is not open?","\nYes — ",[32,1663,1664],{},"QgsProject.instance().read(\"\u002Fpath\u002Fto\u002Fproject.qgz\")"," opens one in place, replacing what is currently loaded. Be aware that it discards unsaved changes to the current project without asking, so it is worth checking ",[32,1667,1668],{},"isDirty()"," first.",[14,1671,1672,1675,1676,1679],{},[451,1673,1674],{},"How do I clear everything the Console has defined?","\nThere is no reset command; restarting QGIS is the reliable way. Within a session you can ",[32,1677,1678],{},"del"," a specific name, but modules already imported stay cached, which is the same behaviour that makes plugin reloading require an explicit module purge.",[14,1681,1682,1685,1686,1689],{},[451,1683,1684],{},"Why does the Console show a different result from a Processing algorithm?","\nUsually a filter. A layer with an active ",[32,1687,1688],{},"subsetString",", or a selection combined with a \"selected features only\" input, makes the algorithm see a different set of features from the one your Console loop iterates.",[14,1691,1692,1695,1696,1698],{},[451,1693,1694],{},"Where does the Console write its output?","\nInto its own pane, not the system terminal. A ",[32,1697,506],{}," from a signal handler that fires later may appear while you are typing something else, which is disconcerting but harmless — use the Log Messages panel instead when the timing matters.",[14,1700,1701,1704,1705,1708],{},[451,1702,1703],{},"Can I import my own modules into the Console?","\nYes, once their directory is on ",[32,1706,1707],{},"sys.path",". Appending a project directory at the start of a Console session is a common way to develop a library and exercise it interactively before it becomes a plugin. Remember that modules are cached, so an edit needs an explicit reload to take effect.",[14,1710,1711,1661,1714,1717,1718,1721],{},[451,1712,1713],{},"Is there a way to time a snippet in the Console?",[32,1715,1716],{},"import time"," and bracket the call, or use ",[32,1719,1720],{},"%timeit"," style repetition by hand. Timing in the Console is a reasonable guide for provider reads and geometry operations, though rendering timings are dominated by the canvas and are better measured with a render job.",[205,1723,1725],{"id":1724},"related","Related",[856,1727,1728,1736,1742,1748,1754,1760,1766,1773],{},[448,1729,1730,1386,1733,1735],{},[451,1731,1732],{},"Up:",[18,1734,21],{"href":20}," — the parent guide that frames the whole environment.",[448,1737,1738,1741],{},[18,1739,1740],{"href":25},"QGIS API Architecture"," — the object model behind the classes you call in the console.",[448,1743,1744,1747],{},[18,1745,1746],{"href":1228},"Setting Up PyCharm for QGIS Development"," — graduate from the console to a full IDE.",[448,1749,1750,1753],{},[18,1751,1752],{"href":222},"Virtual Environments for QGIS and PyQGIS"," — isolate dependencies for reproducible runs.",[448,1755,1756,1759],{},[18,1757,1758],{"href":1248},"Debugging PyQGIS Scripts"," — turn silent failures into actionable tracebacks.",[448,1761,1762,1765],{},[18,1763,1764],{"href":1189},"How to Install QGIS Python Bindings on Windows"," — run PyQGIS outside the console.",[448,1767,1768,1772],{},[18,1769,1771],{"href":1770},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-python-console-basics\u002Faccess-active-layer-and-selection-pyqgis\u002F","Access the Active Layer and Selection in PyQGIS"," — act on exactly what the user has clicked, with checks that fail clearly.",[448,1774,1775,1779],{},[18,1776,1778],{"href":1777},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-python-console-basics\u002Frun-and-save-scripts-in-qgis-python-editor\u002F","Run and Save Scripts in the QGIS Python Editor"," — move from one-line experiments to files you keep and re-run.",[1781,1782,1783],"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);}",{"title":541,"searchDepth":564,"depth":564,"links":1785},[1786,1787,1788,1789,1792,1793,1794,1795,1796,1797,1798],{"id":207,"depth":564,"text":208},{"id":230,"depth":564,"text":231},{"id":439,"depth":564,"text":440},{"id":520,"depth":564,"text":521,"children":1790},[1791],{"id":885,"depth":571,"text":886},{"id":1169,"depth":564,"text":1170},{"id":1233,"depth":564,"text":1234},{"id":1276,"depth":564,"text":1277},{"id":1370,"depth":564,"text":1371},{"id":1503,"depth":564,"text":1504},{"id":1578,"depth":564,"text":1579},{"id":1724,"depth":564,"text":1725},"Get started with the QGIS Python console. Run PyQGIS commands interactively, access layers, execute processing algorithms, and prototype scripts quickly.","md",{"slug":12,"type":1802,"breadcrumb":1803,"datePublished":1804,"dateModified":1805},"guide","Python Console Basics","2025-02-12","2026-07-18","\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-python-console-basics",{"title":5,"description":1799},"pyqgis-fundamentals-environment-setup\u002Fqgis-python-console-basics\u002Findex","2fTNsiLM0HAgpjYcV3I2q4SfKhTruV0_2si581cnFjs",1787823360564]