Run and Save Scripts in the QGIS Python Editor
The console is where PyQGIS starts and a poor place for it to stay. As soon as a task is more than three lines, retyping it after every mistake becomes the work, and the useful version of yesterday's script is somewhere in the scrollback. The editor built into the console panel fixes that for very little effort: a file you can save, re-run with one key, and keep.
This recipe belongs to QGIS Python Console Basics. It covers the editor itself, the import-caching trap that makes edits appear to have no effect, putting your own modules on the path, running a script at QGIS startup, and the point at which an external editor becomes the better tool.
Prerequisites
- QGIS 3.34 LTR (bundled Python 3.12) or newer.
- The Python console open — Plugins → Python Console, or Ctrl+Alt+P.
- A folder you are happy to keep scripts in; anywhere writable will do.
Open the editor and run a script
The editor is the second button on the console toolbar — "Show Editor" — and it opens a tabbed pane beside the console output. Write a file, save it, and press Ctrl+Shift+E to run it. The script executes in the same interpreter as the console, so iface, QgsProject and anything you have already imported are available, and anything the script defines stays available in the console afterwards.
"""Summarise parcel areas by ward — run with Ctrl+Shift+E."""
from qgis.core import QgsProject
def summarise(layer_name="Parcels", field="ward"):
layers = QgsProject.instance().mapLayersByName(layer_name)
if not layers:
raise RuntimeError(f"no layer called {layer_name}")
totals = {}
for feature in layers[0].getFeatures():
totals[feature[field]] = totals.get(feature[field], 0) + feature.geometry().area()
return totals
if __name__ == "__console__":
for ward, area in sorted(summarise().items()):
print(f"{ward}: {area / 10000:.1f} ha")
Breakdown: Wrapping the work in a function and calling it under a guard means the file is useful in two ways: run it and it prints a summary, or import it and call summarise() with different arguments. The guard value is "__console__" rather than "__main__" — that is the module name the QGIS console gives to the script it runs, which is a genuine QGIS-specific detail that catches people out. Keeping the parameters as arguments with defaults rather than constants at the top means the console can experiment without editing the file.
Beware the import cache
The trap that costs everybody an hour once: a script imported as a module is cached, so editing the file and re-running the importer changes nothing.
import importlib
import my_tools
importlib.reload(my_tools)
my_tools.run()
Breakdown: Python caches modules in sys.modules on first import, and a second import my_tools is a no-op. importlib.reload() re-executes the file, which picks up your edits — but only for that module, not for modules it imports, so a package of several files may need reloading in dependency order. This is the same problem plugins have, and the same reason the Plugin Reloader tool exists, as described in Reload a QGIS Plugin Without Restarting. Scripts run from the editor with Ctrl+Shift+E are executed fresh every time and are not affected; only imports are.
Put your own modules on the path
Once a few scripts share helper functions, put them in a folder QGIS can import from.
import sys
folder = "/home/ana/pyqgis_tools"
if folder not in sys.path:
sys.path.append(folder)
from geometry_helpers import densify # your own module
Breakdown: Appending to sys.path at the top of a script works immediately and lasts for the session. For something permanent, the same two lines belong in the startup script described below, or the folder can be added to the PYTHONPATH environment variable before QGIS launches. Guard the append with the membership test or the path accumulates duplicates every time the script runs, which is harmless but makes sys.path unreadable when you are debugging an import problem.
Run code at QGIS startup
QGIS runs a Python file called startup.py in the active profile folder every time it launches — the right place for path additions, small conveniences and anything you want available in every session.
# ~/.local/share/QGIS/QGIS3/profiles/default/python/startup.py
import sys
for folder in ("/home/ana/pyqgis_tools", "/home/ana/shared_gis_helpers"):
if folder not in sys.path:
sys.path.append(folder)
print("PyQGIS tools ready")
Breakdown: The path differs by platform — on Windows it is under AppData/Roaming/QGIS/QGIS3/profiles, on macOS under Library/Application Support — but the profile folder is always reachable from Settings → User Profiles → Open Active Profile Folder. Keep this file small and fast: it runs before the interface appears, and an exception here can prevent QGIS from starting cleanly. It is also profile-specific, which makes it a good way to keep an experimental setup separate from the profile you do real work in.
Know when to move to a real editor
The built-in editor is deliberately modest. Three signs mean it is time to move on, all covered in Setting Up PyCharm for QGIS:
You want breakpoints. Print statements stop scaling somewhere around the third nested function. A real debugger attached to the running QGIS — the workflow in Debug a QGIS Plugin with debugpy — pays for its setup in one session.
The code is more than one file. Multi-module projects need proper navigation, refactoring and an import graph you can see. Reloading three modules by hand in the right order is a signal, not a workflow.
It belongs in version control. Anything shared, scheduled or shipped should be in a repository with tests, which means an editor that understands the project layout.
None of this makes the built-in editor obsolete. It remains the fastest way to run a fifty-line script against the project currently open in front of you, which is a large share of all PyQGIS ever written.
QGIS version compatibility
| QGIS version | Python | Notes |
|---|---|---|
| 3.22 LTR | 3.9 | Editor, Ctrl+Shift+E and startup.py all present. |
| 3.28 LTR | 3.9 | Identical. |
| 3.34 LTR | 3.12 | Baseline for this page. |
| 3.40 / 3.44 | 3.12 | Editor gained better completion and an improved find dialog; behaviour is otherwise the same. |
The console's script module name has been __console__ throughout the 3.x series, but do not rely on it in code that must also run standalone — check for both it and __main__.
Troubleshooting
- Edits to an imported module have no effect. Module caching. Use
importlib.reload(), or run the file from the editor rather than importing it. ImportErrorfor your own module. The folder is not onsys.path, or the file name does not match the import name. Printsys.pathto check.- The script runs but nothing prints. Output goes to the console pane above the editor, which may be scrolled away or collapsed.
- A syntax error points at the wrong line. Mixed tabs and spaces. The editor can show whitespace; turn it on once and the problem is obvious.
startup.pyseems to be ignored. It is in the wrong profile folder. Open the active profile folder from the menu rather than guessing the path.- The script works once and fails on re-run. It mutates state left over from the previous run — an open edit session, a layer already added. Make scripts idempotent.
Conclusion
Use the console for one-liners and the built-in editor the moment a task is worth keeping: save the file, run it with Ctrl+Shift+E, and wrap the work in functions so the console can call them with different arguments. Remember that imports are cached and edits need a reload, add your own folder to sys.path for shared helpers, and use startup.py for anything that should be ready in every session.
Frequently Asked Questions
Does the editor run scripts in the same interpreter as the console? Yes. Everything the script defines is available in the console afterwards, and everything already imported is available to the script.
Why is __name__ not __main__?
The console runs scripts under the name __console__. Check for that value, or for both, if the file should also run standalone.
Where are console scripts saved by default? Wherever you choose; QGIS offers a default folder in the profile directory but does not require it. Keeping scripts with the project they belong to is usually more useful.
Can I run a script without opening QGIS?
Yes, with a standalone setup — see Running Python Scripts Outside QGIS Desktop. Anything using iface will need rewriting first.
How do I share a script with a colleague? A file plus a note about which layers it expects. If it is used often enough to be worth documenting properly, it is probably worth being a Processing script or a small plugin instead.