Remote Debugging Django app running on Apache+mod_wsgi

Jul 18, 2013 at 1:47 PM
I have a Linux server set up with Apache and everything. I usually use PHP, but PTVS seemed like a great reason to try out Python and Django. I got a Django app set up on my server and I went through all the tutorials and have the completed polls application. I am trying to figure out how to attach the remote debugger to my Django app so I can debug it. It would be a great help when I decide to start making more apps.
Coordinator
Jul 19, 2013 at 12:26 AM
Edited Jul 19, 2013 at 12:26 AM
Hi! We have a tutorial for remote debugging here:
http://pytools.codeplex.com/wikipage?title=Remote%20Debugging%20for%20Windows%2c%20Linux%20and%20OS%20X

I would expect you could do the enable_attach call in your project's wsgi.py. Let us know if that doesn't work, and we'll investigate. Thanks!
Jul 19, 2013 at 1:03 AM
I already followed those steps to make sure I could do the remote debugging.

If I run Django through "manage.py runserver", I am able to find the process, but I cannot get any of the break points to work. It appears that Django spawns child processes to handle the requests.

If I run Django through Apache with ptvsd, it does not show up at all. I assume this is because Apache executes wsgi.py on an as needed basis so it is not constantly running. This would only give me the smallest of chance to attach the process before it stop running.

It appears that it is not going to work. Haha. Perhaps, get the remote debugger to work Apache and then pass it off to the python process. I have no idea if that is even possible. As for it not working on "manage.py runserver", does the remote debugger work when the process execution is passed to a new file/process?
Coordinator
Jul 19, 2013 at 1:25 AM
No, it wouldn't work across process forks - it does not intercept process creation, so the new project has pristine state with none of the debugging hooks.

That said, if the newly started process also imports ptvsd, it should work, but then of course you would have to attach to the child process (which implies that it would have to use a different port number for it to distinguish it). The tricky part, then, would be to figure out how to make the port numbers different.
Coordinator
Jul 19, 2013 at 1:27 AM
By the way, is there any particular reason why you're trying to use the remote debugger in the first place? If you're running it on the local machine (which seems to be implied by using manage.py runserver, since that's the development server, not something you should use in production), then you should be able to start debugging it just by launching it from VS (with F5). The only reason to use remote debugger is when you run it on a different machine. Is it because you want to debug it in a production-like environment (e.g. Linux)?
Coordinator
Jul 19, 2013 at 1:44 AM
I have just tried adding enable_attach() at the very beginning of wsgi.py, and this seems to give the ability to attach to the process when it's launched via manage.py runserver, and hits my breakpoints every time a new request is performed from the browser - try that.

For the Apache scenario, you could try blocking the process with ptvsd.wait_for_attach(), though the server might have a time-out for servicing requests that you might need to increase to make this feasible.

All in all, it seems like the model where you enable an attach hook from the process side and then direct VS to attach may not be particularly convenient for server scenarios which are serviced in new-process-per-request mode. We might want to look into supporting the reverse atttach mode, where instead of VS attaching to the script, the script attaches to VS (like PyDev and PyCharm). If you're interested in such a thing, please create a feature request in the issue tracker!
Jul 19, 2013 at 9:54 PM
Edited Jul 19, 2013 at 10:33 PM
The reverse debugger sounds like an awesome idea.

I will try the manage.py runserver one again. Where did you put the break point? Was it in the wsgi.py file? I put a bunch of breakpoints in other files. Also, do you have to use a specific browser for them to be caught? I am using IE 10 (I read IE worked better, somewhere). As for my code and how I have it set up, I have git set up on the same server as the Web page I am push it to the server and then pull it to the install directory and run the code from there. How does it determine that the break point is referring to the code you have open? Maybe it is not recognizing it as the right place to break because I am using git?

I will look into the ptvsd.wait_for_attach() and get back to you on how it works.

As for why I am trying to get it to work on the remote server, that is a two fold answer. One, I do want to test it in a production-like environment. As I have already figured out there is a huge difference between Django on my local machine and my server. Also, I have Django 1.51 on my server and Python 2.7 and locally I have Django 1.4 with Python 1.4. For the most part, they should work the same, but you never know. The second reason, I am also using my personal time to figure out how to implement something like this for a custom framework very similar to Django that the company I work for uses.

EDIT: I was not able to get it work again. Does the Webserver have to be running to port 80? I am changing the server port to something different because I do not want to stop my Apache server. What command are you using to launch the server? Just "python manage.py runserver"? What port are you binding it to? Or would that matter?
Coordinator
Jul 19, 2013 at 10:39 PM
The reverse debugger sounds like an awesome idea.
I'll create a feature request to track this.
Where did you put the break point? Was it in the wsgi.py file?
In my test, I've put the breakpoint inside my view function (the one that is mapped to the URL that I then opened in the browser).
Also, do you have to use a specific browser for them to be caught? I am using IE 10
Which browser you use should not affect it in any way, since the code in question runs on the server, and VS is attached to that server, not the browser. The only case where the choice of browser would matter is when you're trying to debug your client-side JavaScript from VS - it lets you do that, too, but in that case it needs IE. This is not PTVS or Django-related, however.
How does it determine that the break point is referring to the code you have open? Maybe it is not recognizing it as the right place to break because I am using git?
The way the mapping works is that it first tries to open the file with exact same path as what is reported from debuggee. In case of remote debugging this will not work more often than not, but then it should just start matching based on simple file name. You should see if it did the match correctly, because your breakpoints should "light up" then once debugging starts - i.e. show as resolved, which is indicated by a solid red circle. If debugger is attached but breakpoint couldn't be mapped to any file that's actually running, it'll show as an empty circle.
Coordinator
Jul 19, 2013 at 10:40 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Jul 22, 2013 at 11:02 AM
Just to let you know, I am going to try to get it working again once I get back to my apartment. I have been away for the summer and my Internet is pretty terrible. Hopefully better Internet might help. It is so bad I cannot maintain an SSH connection for more then 10 minutes.