|
| 1 | +--- |
| 2 | +description: 'How to debug Nitric Python applications locally' |
| 3 | +tags: |
| 4 | + - Debugging |
| 5 | +languages: |
| 6 | + - python |
| 7 | +published_at: 2025-03-27 |
| 8 | +updated_at: 2025-03-27 |
| 9 | +--- |
| 10 | + |
| 11 | +# Debugging |
| 12 | + |
| 13 | +This guide will walk you through seting up local debugging for Nitric applications written in Python. |
| 14 | + |
| 15 | +## Local Debugging with Python |
| 16 | + |
| 17 | +Debugging serverless-style applications can be challenging due to the way functions are triggered by events. For Python, [`debugpy`](https://github.com/microsoft/debugpy) is used to connect a debugger to the service while it runs. |
| 18 | + |
| 19 | +Nitric's local environment behaves as closely as possible to the target cloud environment. While local debugging can help uncover many issues early, unit testing and integration testing are still strongly recommended prior to deploying to production. |
| 20 | + |
| 21 | +### 1. Modify the Python entry point |
| 22 | + |
| 23 | +Add the following lines to the top of the service file (e.g., `main.py`). This starts a debug server that the IDE can attach to. |
| 24 | + |
| 25 | +```python |
| 26 | +import debugpy |
| 27 | + |
| 28 | +host, port = debugpy.listen(("0.0.0.0", 52509)) # Static port for consistent debugging |
| 29 | +print(f"✅ Debugpy is listening on {host}:{port}", flush=True) |
| 30 | +``` |
| 31 | + |
| 32 | +> A **static port** (`52509`) is used so the IDE knows which port to connect to. Update the `launch.json` configuration to match this port before starting the debugger. |
| 33 | +
|
| 34 | +### 2. Update `nitric.yaml` |
| 35 | + |
| 36 | +Modify the `start` command to include an auto-reloader and ensure Python does not use frozen modules, which can interfere with `debugpy`, E.g. |
| 37 | + |
| 38 | +```yaml |
| 39 | +name: message-board |
| 40 | +services: |
| 41 | + - basedir: '' |
| 42 | + match: services/*.py |
| 43 | + runtime: python |
| 44 | + start: uv run -- watchmedo auto-restart -p "*.py" --no-restart-on-command-exit -R -- python -Xfrozen_modules=off $SERVICE_PATH |
| 45 | +batch-services: [] |
| 46 | +websites: [] |
| 47 | +runtimes: |
| 48 | + python: |
| 49 | + dockerfile: ./python.dockerfile |
| 50 | + context: '' |
| 51 | + args: {} |
| 52 | +``` |
| 53 | +
|
| 54 | +> This configuration restarts the service on file changes and includes the necessary flags for debugging compatibility. |
| 55 | +
|
| 56 | +### 3. Configure `launch.json` in VS Code |
| 57 | + |
| 58 | +VS Code uses a launch.json file to define how it should start or attach to a debugging session. In this case, the debugger doesn't launch the application itself—it attaches to the running service that was started manually from the terminal. |
| 59 | + |
| 60 | +To create or update the launch.json file: |
| 61 | + |
| 62 | +- Open the Run and Debug panel in VS Code (Ctrl+Shift+D or from the sidebar). |
| 63 | +- Click "create a launch.json file" if one doesn't already exist. |
| 64 | +- Choose "Python" when prompted for the environment. |
| 65 | +- Replace the default configuration with the following: |
| 66 | + |
| 67 | +```json |
| 68 | +{ |
| 69 | + "version": "0.2.0", |
| 70 | + "configurations": [ |
| 71 | + { |
| 72 | + "name": "Python Debugger: Remote Attach", |
| 73 | + "type": "debugpy", |
| 74 | + "request": "attach", |
| 75 | + "connect": { |
| 76 | + "host": "localhost", |
| 77 | + "port": 52509 |
| 78 | + }, |
| 79 | + "pathMappings": [ |
| 80 | + { |
| 81 | + "localRoot": "${workspaceFolder}", |
| 82 | + "remoteRoot": "." |
| 83 | + } |
| 84 | + ] |
| 85 | + } |
| 86 | + ] |
| 87 | +} |
| 88 | +``` |
| 89 | + |
| 90 | +> Ensure the `port` matches the value used in the `debugpy.listen()` call. If the port changes in the code, update it here as well. |
| 91 | + |
| 92 | +### 4. Running the debugger |
| 93 | + |
| 94 | +Start your nitric service with `nitric start` and start the debugger. |
| 95 | + |
| 96 | + |
| 97 | + |
| 98 | +In the Terminal, both the Nitric runtime output and the debugpy listener output will be visible, including the active debug port. |
| 99 | + |
| 100 | +In this example, a breakpoint has been hit on line 16 of `message_api.py`, within an HTTP handler for the `/messages` endpoint. |
0 commit comments