This article is written for all those people using Pycharm but wishing to switch to VSCode for a reason. And also for beginners not knowing how to setup the visual debugger in VSCode for python yet.
The article is written at the request of multiple people who work with python through dev env setups with docker-compose, and needing connect to already existing containers and start dealing with python efficiently in it.
In the article, we also cover the ability to run visual debug for specific unit tests, and stress the importance of doing it, because it helps us having comfortable entrypoints into our code with maximum visibility. That makes test-driven development very plausible, or at least development when tests are written at the end of an atomic change made by pull request, for the reasons of having the ability to see rapid feedback and trying to your code parts literally from within unit tests.
Article as main point guides people how to setup things for working with Python for Django in already running Docker containers, but we provide also explanation of doing it without docker, and also for Fastapi, and Flask for comparison.
Previous zero knowledge of VSCode usage is assumed. Basic knowledge of how to use pip
and venv
is assumed.
All examples in the article are in the examples folder.
We assume you’re opening VSCode with the working directory set to a specific example folder (e.g., examples/simple_pyscript
or examples/django_example
) so that the .vscode
folder is at the project root.
P.S. In normal projects reopening workdir with code -r .
is not required, as we open projects only once, but we will be often using it in this article to switch between multiple working directories when necessary.
examples/simple_pyscript
.code -r .
shortcut allows quickly reopening VSCode with changing working directory.
In normal projects reopening workdir with code -r .
is not required, as we open projects only once, but we will be often using it in this article to switch between multiple working directories when necessary.First, ensure you installed Pytest Explorer
extension. It will autoinstall Python extension for intellisense along the way.
@id:littlefoxteam.vscode-python-test-adapter
@id:ms-python.python
If smth is working weirdly, like syntax highlighting by colors is not present, make sure to run Ctrl + Shift + P and write Reload Window. Select and apply, it quickly reloads VSCode, including reloading extensions.
After that python simple file debugging is launchable as git clone/download https://github.com/darklab8/blog/tree/master/
git clone https://github.com/darklab8/blog.git
cd blog/blog/articles/article_detailed/article_visual_debugger_in_vscode/examples
cd simple_pyscript && code -r # will reopen to different workdir
In the left sidebar, click on file.py
in the directory tree.
Select in the top menu: Run -> Star Debugging (F5)
Now let’s check it is working for pytest test debug:
# create venv
python3 -m venv .venv
# activate
source .venv/bin/activate # at windows can be `venv\Scripts\activate`
pip install -r requirements.txt
Select a new venv in VSCode using one of these methods:
.venv/bin/python3
manually if needed.Ctrl + Shift + P
> Enter interpreter path
CMD + P
> Python: Select Interpreter
If smth glitches, we do Ctrl + Shift + P -> Reload Window
trick
cd ../simple_py_with_settings && code -r .
You can update .vscode/settings.json
to set up your debug parameters.
cat .vscode/settings.json
will show content:
{
"python.testing.pytestArgs": [
"."
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"terminal.integrated.env.linux": {
"SOME_VAR": "abc"
},
"terminal.integrated.env.windows": {
"SOME_VAR": "abc"
},
"terminal.integrated.env.osx": {
"SOME_VAR": "abc"
}
}
$ python3 file.py
Example(foo=10, bar='abc', is_smth=False)
Those env vars will be available for access from within the launched web server and unit tests during visual debug usage too.
cd ../django_example && code -r .
set a breakpoint in a view at urls.py
and launch Python Django debug, like in this picture below
Debug for Django will work due to the present .vscode/launch.json
containing
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Django",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": ["runserver", "0.0.0.0:8000"],
"django": true,
"justMyCode": false
},
{
"name": "Python: Debug Tests", // KO with GUI (tests tab)
"type": "debugpy",
"request": "launch",
"program": "${file}",
"purpose": ["debug-test"],
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Debug specific tests", // OK with F5
"type": "debugpy",
"module": "pytest",
"request": "launch",
"purpose": ["debug-test"],
"console": "integratedTerminal",
"justMyCode": false,
"args": ["test_sample.py::test_answer"]
},
{
"name": "Python: Current File", // OK with F5
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "internalConsole",
"justMyCode": false
}
]
}
Of all the settings, only the Python: Django
section matters for running the debugger via manage.py
right now.
Take note that you can technically input arbitrary arguments (under args
key) to run it for execution of more different stuff
take note of setting "justMyCode": false
, it allows you navigating during visual debug third party libs too. Otherwise, they will be skipped.
Crucial thing when debugging internal company libs, or when developing your own library that is doing smth with known third-party libs.
The justMyCode: false
setting in launch.json
allows navigation through third-party library code, even during visual debugging from unit tests.
cd ../fastapi_example && code -r .
Install packages in virtualenv again:
deactivate
python3 -m venv .venv
source .venv/bin/activate # at windows can be `venv\Scripts\activate`
pip install -r requirements.txt
with small fixes to .vscode/launch.json
, we have it adapted for fastapi now
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Fastapi",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/app.py",
"justMyCode": false
},
{
"name": "Python: Debug Tests", // KO with GUI (tests tab)
"type": "debugpy",
"request": "launch",
"program": "${file}",
"purpose": ["debug-test"],
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Debug specific tests", // OK with F5
"type": "debugpy",
"module": "pytest",
"request": "launch",
"purpose": ["debug-test"],
"console": "integratedTerminal",
"justMyCode": false,
"args": ["test_sample.py::test_answer"]
},
{
"name": "Python: Current File", // OK with F5
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "internalConsole",
"justMyCode": false
}
]
}
With written small code examples in app_test.py
we have no trouble launching visual debug for unit tests of fastapi
See folder flask_example
for almost same example to try for Flask too.
Ensure having installed Dev Containers app @id:ms-vscode-remote.remote-containers
cd ../examples/django_example
docker compose build
docker compose run --service-ports shell # `--service-ports` option ensures we forwarded 8000 port written in docker-compose despite using `run` command instead of `up`
Instead of docker-compose usage, same is achievable with regular docker
command:
docker build --tag test
docker run -it -v $(pwd):/code -w /code --name shell --entrypoint=bash test
Now we can enter the already running container by using Attach Visual Studio Code option.
This option opens a second VSCode instance, running from within the container.
Install Pytest Explorer @id:littlefoxteam.VSCode-python-test-adapter
(with autoinstalled Python inside).
Since the extension is installed inside a running container, you’ll need to repeat the installation each time a new container is created or started.
In the left sidebar go to the working directory /code
If everything is set up correctly, you’ll see green arrows next to test functions, allowing you to run them in debug mode. (Green arrow at the left of a line code)
You can also launch the web server from the Debug menu by selecting Python: Django
.
To ensure that we are able to see dev server from the container, ensure we binded it to 0.0.0.0
instead of localhost
!
That is doable with python3 manage.py runserver 0.0.0.0:8000
for django, we added missing argument into .vscode/launch.json
.
after setting breakpoint in view, and visiting
http://localhost:8000/polls
we get being stopped in breakpoint as desired.
The same steps are doable for FastAPI and Flask. We added Dockerfile and docker-compose.yml for the same into fastapi_example and flask_example folders.
P.S. When you are in VSCode from within container, opened terminal is opened automatically for within the container shell
Congratulations, now you are able to use visual debug for python common web frameworks without and with docker for web server run itself and unit tests!
With showing examples how it is done for two different python frameworks, where for fastapi we adjusted launch.json on a fly, it is my intention that you will be able to see how to do it similarly for any other existing python framework.
I encourage you to try development from within unit tests written with visual debug, since it is actually a comfortable way of having testing as part of a working code writing. Doing that will ensure most rapid feedback, and ensure you a writing better code in all kind of code internal characteristics. Do check books like TDD by kent beck and Unit testing by Vladimir Khorikov in order to find out more about unit testing that enables writing maintainable code.
We showed examples with Docker, because modern web development could be having different C depended libraries, that without docker is very struggling to install otherwise. Also, docker makes universal way to setup dev envs for many people and documents as a code how your application is buildable. Some companies just keep dev env straight in docker only for those reasons.