6 min read Author: klaas

Debugging a PythonOnWheels application with VSCode

in this short hands on tutorial you will learn how to debug a Tornado/PythonOnWheels application with VisualStudio Code (VsCode). In fact this a really simple task. I assume that you already installed PythonOnWheels, created a project and added a virtual environment. It is really handy to setup debugging in VSCode because it really eases the development. And it also looks great ;) Since PythonOnWheels is Tornado based, this will also work for any other tornado Application. 

Teaser: this is what we get in the end. Really nice and helpful.

Pre-Prerequisites:

Install PythonOnWheels and create a project. PythonOnWheels is a Tornado based web-framework for Python based on the "ruby on rails workflow". Installing PythonOnWheels and setting up a project is just a matter of minutes and works on Windows, Linux and Mac. If you don't know how to do this just read the short getting started documentation (5 Minutes). 

Prerequisites:

  • created a new PythonOnWheels (PoW) app called debugtest
  • add a virtual environment in the folder debugtest/venv
  • install the pow requirements.
  • install VSCode (if you do not have already)
  • install the python extension for vscode  (if you dont have that already as well)

Setup debugging for your project:

1) Set the python interperter

In VSCode first select the "correct" python interpreter to use for your project. Which is the one from your project's virtual environment. 

  • Open the Command Palette (Views->Command Palette
  • choose: Python: Select Interpreter 
  • now choose the one pointing to your current ./venv/.  (This is a little different on windows :.\venv\Scripts\python.exe and Linux/OSX where it is: ./venv/bin/python)

2) Configure the debugging setup

  • Click on the debug icon to open the VSCode debug view (or go to view->debug)

Right next to the "start debugging" arrow You can see that there is currently no configuration for this project. 

  • Just click the dropdown next to "No Configurations" and:
  • Click on "Add configuration"


  • Choose the configuration template for: Python File (This will create and open a dummy launch.json file for us.)


Now the important part:  create the configuration for a PythonOnWheels / Tornado project

  • replace the launch.json content with the following 

{  
// 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: PoW",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/server.py",
"args": [],
"console": "integratedTerminal"
}
]
}

  • Now save your launch.json file. This is how it should look now:

This configuration (named: "Python PoW") will basically just use your configured python interpreter to launch the server.py file in your current project directory (${workspaceFolder}). And this is enough to start and debug your web application with vscode. You can also add command line arguments in the args[] array, or even add environment variables by adding an env[] array , but we  don't need that for the moment.

So let's test this with a debugging session.

  • Switch back to VSCode file explorer and open your hello_world handler (handlers/hello_world.py)
  • Add a breakpoint in line 10 by just left-click before the line number. This will add a red ball before the line
  • Switch back to debug view: (click the bug icon or go to view->debug). This will open an "empty" debug view. Keeping your current file open so you can still easily see your breakpoint. (You can also see all breakpoints of your project in the bottom left of the debug view.)
  • Now start a debugging session by clicking the green play icon next to your Python PoW config. This will start a debugging session with the setup we just configured in our launch.json. Make sure that the config is named: Python PoW

You can See in the picture below that this automatically adds a terminal view which shows that the PythonOnWheels application sucessfully started (in the bottom right). And you also get some control icons in the upper right of VSCode.

Let's hit the breakpoint

But we don't see any value added debugging informations so far since the application did not hit our breakpoint yet. It is just in the Tornado IOLoop waiting for requests to come. To force this:  

  • Now open a browser and go to the /hello URL of your project. If anything is default (as in my case) this is:

http://localhost:8080/hello

This is what VSCode shows us now:

You can see the small yellow arrow around our breakpoint. This is where the application is right now. It stopped execution just before executing line 10. If you look at your browser window in parallel, you will also notice that your Browser request does not finish. This is because we did not execute the response:

self.write("hello world") 
You can also see tons of useful information about variables that are currently available to the scope of the HelloHandler instance that the debugger loaded and displays for us. I think you'll agree that this is truely much more helpful than just a few prints. And by the way you can see any print() debug info you want to use in the Terminal window below as well. 

So we really have the best of both worlds here in one view:

Aditionally you can see the call stack. Which shows us the PythonOnWheels application flow.

http request -> Server -> Base Handler -> Route + Request Type (GET, POST.. ) => actual handler / method call.

In this case:

http request (/hello, GET) -> Server -> Base Handler -> /hello+ Request Type (GET) => HelloHandler.hello_world()

Continue the application and finish the request

To control your application you can use the control bar in the upper right. Finish the request by clicking the blue "Pause/Play" icon (Or press F5)

Two things will happen:

  • Your browser now shows "hello world!" (so the request really finished"
  • The debug view becomes empty again, because our application is in the applications IOLoop again, waiting for new requests.

Next: Test it out, play around

I really recommend to play around a little with this and inspect all the infos available to you in the Variable view. I just want to point out the request Variable which contains all the information that the browser send witrh the request and is available to you in the application. This is an excertp which came with the /hello demo call (Firefox). Lot's of info about the path, request-body, cookies, .....


This is it

Hope this is helpful for you. (At least this is very helpful for me ;). By the way, this way of configuring debugging is of course also applicable not only for Tornado/PythonOnWheels but for many other python projects you may use. Almost always just define the correct python interpreter and add a basic launch.json.