How to debug Django in VSCode with autoreload turned on - python

I set up debugging in VSCode (Django application) and it works great with the default setup. However, when debugging it seems automatic reloading is not possible. This is stated in the VSCode docs:
Note that automatic reloading of Django apps is not possible while debugging.
I was wondering if there's some way to make debugging (breakpoints etc.) work with reload enabled in Django.

It turns out you can make this work by using Microsoft's debugpy tool.
Django launches two processes when reloading is turned on (the default), one of them is the parent and the other is the subprocess which does the reloading magic.
Django differentiates these two processes by setting the environment variable RUN_MAIN to true in the subprocess (which does the reloading). Refer to: https://github.com/django/django/blob/8a902b7ee622ada258d15fb122092c1f02b82698/django/utils/autoreload.py#L241
By tweaking manage.py slightly, we can start a debug listener in the parent process and have it survive any reloads.
Add debugpy to however you manage your requirements (requirements.txt etc.)
Add the following function to initialize the debugger:
def initialize_debugger():
import debugpy
# optionally check to see what env you're running in, you probably only want this for
# local development, for example: if os.getenv("MY_ENV") == "dev":
# RUN_MAIN envvar is set by the reloader to indicate that this is the
# actual thread running Django. This code is in the parent process and
# initializes the debugger
if not os.getenv("RUN_MAIN"):
debugpy.listen(("0.0.0.0", 9999))
sys.stdout.write("Start the VS Code debugger now, waiting...\n")
debugpy.wait_for_client()
sys.stdout.write("Debugger attached, starting server...\n")
Alter the main function in manage.py as follows:
def main()
# <...>
initialize_debugger() # add this
execute_from_command_line(sys.argv)
Modify launch.json configuration in VSCode to attach to port 9999 (from above):
{
"name": "Python: Remote Attach (DebugPy)",
"type": "python",
"request": "attach",
"port": 9999,
"host": "localhost",
},
TIP: you can disable "Uncaught exceptions" because the reload itself causes a SystemExit

Related

How to remotely debug Python with IntelliJ?

Is there a way for remotely debugging Python3 with IntelliJ? I couldn't find any options for it. With VS Code, it's as simple as having this file:
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Remote Attach",
"type": "python",
"request": "attach",
"connect": {
"host": "172.18.0.5",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "."
}
],
"justMyCode": true
}
]
}
and everything works like a (py)charm!
How can i do it with IntelliJ?
I examined all of JetBrains' tutorials, but none seemed to fit what I was searching for.
IntelliJ IDEA and PyCharm both support Remote Debugging with Python, just follow the guide here:
https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html
If you are using IntelliJ IDEA, you may install the Python plugin first, by Settings > Plugins > Marketplace, inputting Python, and then clicking the Install button.
And here is the step to step guide on Remote debugging with the Python remote debug server configuration https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html#remote-debug-config:
Let IDEA/PyCharm host a debugger server on the machine your IDE runs on locally:
Note: This step is a lot different compared with VS Code(Sorry I know little about that tool), in VS Code it's using the package https://github.com/microsoft/debugpy, but it first will call python -m debugpy --listen 0.0.0.0:5678 ./myscript.py to create a debug server on the remote machine/docker, then the Client(here is VS Code) connect to it. But in IDEA/PyCharm it's just the opposite: Python Debug server is listening on the local machine, and the remote script will connect to the IDE's server.
From the main menu, choose Run| Edit Configuration.... The Run/debug configurations dialog opens. You have to click Add configuration on the toolbar, and from the list of available configurations, select Python Debug Server.
Please change the port to a different number between 0 and 65535, default value 0 will not work here, then remember the steps above the IDE host name area.
More info about the IDE host name: the user may specify another host if the debug server is not in the same machine (default is the localhost). In your case you want to connect it from a container, you may change it to the IP of your current machine.
You may also set up the Path Mapping: by clicking the folder selector and then selecting the real folder path as ${workspaceFolder}.
Then click OK button to save it, and then you click the run button to let the debug server run up and listen on remote code to connect to it, it will display something like this in the Debug tool window:
Starting debug server at port 12,345
Waiting for process connection…
Use the following code to connect to the debugger:
import pydevd_pycharm
pydevd_pycharm.settrace('some ip address', port=12345, stdoutToServer=True, stderrToServer=True)
Install and run debug server client in remote machine/container
On your container, execute the following one-time commands in the terminal(In case you are using IDE 2022.3):
pip3 install pydevd-pycharm~=223.8214.51
Then modify the Python file you want to debug by adding lines at the begging of the source file(THIS STEP IS MANDATORY), for eg:
#==============this code added==================================================================:
import pydevd_pycharm
pydevd_pycharm.settrace('some ip address', port=12345, stdoutToServer=True,
stderrToServer=True)
# ... The other codes remain as is
Then you may start remote debugging by just executing the below command in the terminal of the remote machine/container:
python3 myfile.py
Return to the local IDE and begin debugging
Just after step 2, now the local IDE will begin the debugging.
And the final result may look like this:

How to use the vscode python debugger with a project built with bazel?

I want to debug a python file which has a few dependencies that only appear in the runfiles from bazel. How can I debug a bazel build with the vscode debugger?
As someone famous said, "Yes, we can".
You would need to use the "ptvsd" python package.
One-time Setup
Add "ptvsd" as a Python dependency in Bazel
In VS Code, in your launch.json file, add the following configuration:
{
"name": "Python: Attach",
"type": "python",
"request": "attach",
"port": 5724,
"host": "localhost"
},
Debug
When you want to debug a specific file:
In the Python file you want to debug, add the following lines:
import ptvsd
ptvsd.enable_attach(address=('localhost', 5724), redirect_output=True)
print('Now is a good time to attach your debugger: Run: Python: Attach')
ptvsd.wait_for_attach()
Run Bazel on this file as you normally would (bazel run :server for instance)
Execution will stop at "Now is a good time to attach your debugger: Run: Python: Attach"
In VS Code, click on the "Python: Attach" debug option that we setup earlier:
That's it!
Feel free to change the port, 5724 in this example.
ptvsd is deprecated, replaced by debugpy.
Usage is the same as the accepted answer, except that the code snippet for the Python file has changed:
import debugpy
debugpy.listen(5678)
debugpy.wait_for_client() # blocks execution until client is attached

Setting environment variables for integrated terminal

I am seeking help figuring out how to setup environment variables for integrated terminal within Visual Studio Code. Currently I am able to do so with .env file inside my workspace folder, but I'd like to change the filename for this file and create another one or two, let's say dev.env and prod.env. Setting "python.envFile" for my workspace doesn't do the trick and from what I understand changing things in launch.json is for debugging.
The overall goal of all this (and that is important) is to run flask shell (integrated shell for flask web framework, python) with a certain set of env variables and be able to change them by swapping files. I know I could set these by introducing "terminal.integrated.env.osx" to my workspace settings, but I'd rather get these variables from a file.
Thanks a lot for your time and help.
UPD >>
I guess one way to go about it would be to create two tasks as such:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "FLASK SHELL DEV",
"type": "shell",
"command": "source ${workspaceFolder}/dev.env && ${config:python.pythonPath} -m flask shell",
"problemMatcher": []
},
{
"label": "FLASK SHELL PROD",
"type": "shell",
"command": "source ${workspaceFolder}/prod.env && ${config:python.pythonPath} -m flask shell",
"problemMatcher": []
}
]
}
but the question stands. Is there a way to do the same with integrated terminal?
Yes, you can use one of these settings (depending in your platform):
"terminal.integrated.env.linux": {},
"terminal.integrated.env.windows": {},
"terminal.integrated.env.osx": {
"PYTHONPATH": "${workspaceFolder}/src:${env:PYTHONPATH}"
},
However, they will only work for the integrated terminal, not for any other processes the vs code python extension might spawn (tests, linting, debugger). For those you need to use the .env file.
Edit:
It is worth noting that if you start VS Code from the terminal it should inherit any env variables from terminal environment (at least for all the spawned subprocesses, probably not for the integrated terminal).
If you don't want to set environment variables using the terminal you can do it using configuration files.

Python remote debuging with PyCharm and ptvsd

I have a virtual machine running a python process and I want to debug it from my host.
My virtual machine ip is 192.168.10.20.
As per the instructions I set up my launch.json as
{
"name": "Python: Attach",
"type": "python",
"request": "attach",
"localRoot": "/Users/wrkspace",
"remoteRoot": "/home/wrkspace",
"port": 3000,
"secret": "my_secret",
"host": "192.168.10.20"
},
I have two files,one on my host machine and on my vm called test.py which is a helloworld asking for a user input
My host machine has this at the top of the file
ptvsd.enable_attach("my_secret", address = ('192.168.10.20'3000))
# Enable the line of source code below only if you want the application
to wait until the debugger has attached to it
#ptvsd.wait_for_attach()
While on my vm, where I want to debug
ptvsd.enable_attach("my_secret", address = ('192.168.10.20'3000))
# Enable the line of source code below only if you want the application
to wait until the debugger has attached to it
ptvsd.wait_for_attach()
Once I run my attached debugger and then I kick of the test on my vm by going python test.py. It looks like it does something but then fails with
There was an error in starting the debug server.
Error="code":"ENETUNREACH","errno":"ENETUNREACH","syscall":"connect","address":"192.168.10.20","port":3000}
There was an error in starting the debug server. Error = {"code":"ENETUNREACH","errno":"ENETUNREACH","syscall":"connect","address":"192.168.10.20","port":3000}
Is there something I'm missing?
A few steps to trouble shoot these:
1) test the debug port to make sure it is open using "nc -zv test.com 30302"
2) make sure your webserver is not reloading the app after debugger was connected to it. this is the option for flask: " use_reloader=False"

How does django settings tied to web application

Suppose i my web application running with following settings
LOG_DIR = "/var/log/main"
This variable defines where the log should go.
Now then i run my tests and i have test_settings like
from settings import *
LOG_DIR = "/var/log/test"
Now i want to know that does that mean while my test script is running then my main application logs will also go to test folder because i have chnaged the global variable.
For my integration testiing i need to change variables if am afraid that if that will affect the main application or not .Like my application depends upon
Shell ENV variables . I wanted to chnage that for my tests. but i am afraid that if that will chnage the main running application.
This is not for PROD but for other testing applications environment
Running a django process will not affect the settings of another process. Just make sure to explicitly pass the --settings flag to your manage.py script when you run your tests/dev server/ etc..
e.g.
python manage.py test --settings project/settings/test.py
python manage.py runserver --settings project/settings
I prefer having a set of shell scripts that get sourced when I run my test environment (you can configure that with a test runner, see the docs).

Categories