A technical tutorial brought to you by OpenCraft : ) This article was written by team member Paulo Viadanna.
Introduction
The move to using Docker for the Open edX® devstack brought many improvements to our workflow, but it isn’t obvious how to use a key developer tool with the Docker-based devstack: a python debugger.
With recent changes to Visual Studio Code, it’s now possible for VS Code users to get Intellisense and debugging working with your containerized devstack LMS. This will give you as-you-type auto-completion of most python code, near-real-time pylint linting using edX®’s linting rules, and the ability to step through edxapp’s execution and pause and inspect variables while it runs.
Tutorial
Make sure VS Code is up to date (the beta/insiders build is not required anymore, but you do need the latest release)
The first step is to install the Remote – Containers VS Code extension (or the Remote Development Pack if you also want the SSH remote extension) and start up your Open edX devstack (make dev.up) if it’s not already running.
Then we need to install the debugger package into the edxapp venv:
$ make lms-shell $ pip install ptvsd
Alternatively, you can add ptvsd to edx-platform/requirements/edx/private.in and run pip-compile private.in, before provisioning your devstack. This will ensure it always gets installed during provisioning.
Now we’ll create a specific workspace to save our settings. In your edx-platform repository, create a .vscode folder, which will be ignored by git. Put the following into edx-platform/.vscode/edxapp-remote.code-workspace:
{ "folders": [ { "path": "/edx/app/edxapp/edx-platform" } ], "settings": { "python.pythonPath": "/edx/app/edxapp/venvs/edxapp/bin/python", "python.linting.pylintEnabled": true } }
Next, we must create a Launch Configuration to enable debugging, by putting the following into edx-platform/.vscode/launch.json:
{ "version": "0.2.0", "configurations": [ { "name": "Python: Remote Attach to LMS Container", "type": "python", "request": "attach", "port": 5678, "host": "localhost", "justMyCode": false, "pathMappings": [ { "localRoot": "/edx/app/edxapp/edx-platform", "remoteRoot": "/edx/app/edxapp/edx-platform" } ] } ] }
Finally, we need to make sure the LMS enables debugging via ptvsd. Add the following to edx-platform/lms/envs/private.py:
import os import ptvsd if os.environ.get('RUN_MAIN') or os.environ.get('WERKZEUG_RUN_MAIN'): ptvsd.enable_attach(address=('0.0.0.0', 5678), redirect_output=True)
Now Press F1 to open the Command Palette, and choose Remote-Containers: Attach to Running Container…
Select the edx.devstack.lms container.
This will open a new Visual Studio Code window, this time running inside the LMS container. Now we will be working on this VSCode window.
Open the workspace created earlier by choosing File > Open Workspace and open /edx/app/edxapp/edx-platform/.vscode/edxapp-remote.code-workspace
We’ll also need to install the Python extension inside the container. Click on the Extensions tab of VS Code on the left of the window. Note that most of your extensions are not available yet. Find the Python Extension in the “Local – Installed” panel, and click “Install on Attached Container”
And you are now ready to start developing and debugging. You will now have python Intellisense, linting, and debugging with breakpoints and local variables working! (At least for the LMS; for Studio, repeat as needed).
To attach the debugger to the LMS process that’s always running in the container, just hit Debug > Start Debugging or press F5. Note that if you make any changes to the code, Django will restart and that will disconnect the debugger, so you’ll have to reconnect.
You can visit the official discussion forum for questions or reach out to us if you need any support. Happy debugging!
Comments
Leave a ReplyIt is confusing after the step … and choose the edx.devstack.lms container. This will open a new Visual Studio Code window, and you’ll see this in the bottom left:
Are you suppose to do the remaining steps in the new window that just opened or in the original vs code window
Hey Jon, nice to meet you.
From that point on, you should be working on the new window as that’s the one connected to the LMS container.
Thanks for your comment, it was unclear indeed, I made a small adjustment to the blog post.
Cheers!
Hello Paulo,
Many thanks for this helpful tutorial.
I followed it successfully with both lms and studio containers.
Yet more hint could be helpful here:
When trying to debug my external xblock, I placed a breakpoint in the appropriate
python file.
A solid logging indication proved that the studio container passed through the code
(i.e. make studio-logs shows the relevant python logging.info(‘some text’) message)
But the breakpoint was not hit.
I ran some invalid tries to change the launch.json file “pathMappings”
“pathMappings”: [
{
“localRoot”: “/edx/app/edxapp/edx-platform”,
“remoteRoot”: “/edx/app/edxapp/edx-platform”
}
An Idea/hint will be appreciated
Regards
Guy
Hey Guy,
I’m glad you found this guide helpful. Can you better explain the specific code that didn’t hit the breakpoints?
Did you try setting a breakpoint in Studio code to ensure the breakpoints are being hit at all?
I have previously debugged XBlocks installed with
pip install -e /edx/src/xblock-
using this integration. I’ll validate the settings and update the blog post accordingly.Cheers!
Hi,
Indeed breakpoint hit/triggered when placed in courses.py file
while VSCode is attached to the lms container:/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/courses.py
Hits occur as well when breakpoints placed at the preview.py file, while VSCode is attached to the studio container:/edx/app/edxapp/edx-platform/cms/djangoapps/contentstore/views/preview.py
But there are files where active breakpoints (red points) are not hit although loggings.info(‘just was in’) messages do indicate (with make lms-logs) that the code was executed.
Initially I thought it was only files from my Xblock.
This Xblock was installed with proper line in
docker-compose.yml file under the
studio and lms command:
with
pip install -e /edx/app/edxapp/edx-platform/src/MyXlock/
But then I saw similar phenomenon with breakpoints placed in native open edx files such as
/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/views/views.py
I placed a breakpoint at the submission_history(..) method (line 1341) that is activated when I’m logged in as staff user and jump in the browser from the studio to preview.
Then push the SUBMISSION HISTORY button.
Again, certainty of code execution was gained with make lms-logs that showed messages triggered with logging.info(‘submission_history : Message’)
Hopefully this description is more accurate and easy to reproduce,
Otherwise a detailed list of required info could be helpful.
Regards
Guy
I see, thanks for the further information, Guy. (I’m answering the first post to keep a thread)
Just another question, what OS are you using? I had a hard time getting it to attach correctly some time ago on MacOS but it’s working fine for me now.
I’ll take the information you provided and try to replicate the issue.
Cheers!
Paulo hi,
It is
Ubuntu 20.04.2 LTS
But F.Y.I
I do manage (starting this morning) to hit those breakpoints and do not know to
spot any relevant changes I did in my environment aside a restart.
Seems like its better to ignore this thread until further similar complains rises.
Sorry for the “null-disturbance”.
Guy
Hi Guy, no worries as this is no disturbance.
We are glad to see this is helping other developers, feel free to get in touch at any time.
Cheers,
Paulo
Hi paulo, first of all this is a super helpful post.
I had one small concern and I was wondering if you could help me out. Whenever I make any changes in the new vscode window (the one with the container attached to it), the server/container is not refreshed and the changes aren’t reflected. Doing the same change in pycharm, for instance, reloads the server and the changes are reflected.
By the way, I am not making these changes in debug mode.
Is there any setting I missed here?
Hello Munam, I’m glad this helped you.
Saving changes to files in `edx-platform` should restart the server in any case, as that’s controlled by Django `runserver` management command.
There’s an alternative launch method where VScode runs the management command itself with a `–noreload` but that’s not the case with the above attach method.
Can you run `# ps -ef | grep runserver` and check it wasn’t started with that argument?
E.g.
`root 8 7 2 22:00 pts/0 00:00:08 python /edx/app/edxapp/edx-platform/manage.py lms runserver 0.0.0.0:18000 –settings devstack_docker`
Hi Paulo, I followed the steps and, when hitting F5, I got an error:
“connect ECONNREFUSED 127.0.0.1:5678”, with a button suggesting to open the lauch.json file.
Hello Pedro, can you check the lms-logs and see if the server is running alright? Also, what version of the devstack are you running? I have just checked this working on a master devstack.