seaders
seaders

Reputation: 4096

How to remote debug Flask request behind uWSGI in PyCharm

I've read some documentation online about how to do remote debugging with PyCharm - https://www.jetbrains.com/help/pycharm/remote-debugging.html

But there was one key issue with that for what I was trying to do, with my setup - Nginx connecting to uWSGI, which then connects to my Flask app. I'm not sure, but setting up something like,

import sys
sys.path.append('pycharm-debug.egg')

import pydevd

pydevd.settrace('localhost', port=11211,
                stdoutToServer=True, stderrToServer=True,
                suspend=False)
print 'connected'

from wsgi_configuration_module import app

My wsgi_configuration_module.py file is the uWSGI file used in Production, i.e. no debug.

Connects the debugger to the main/master process of uWSGI, which is run once only, at uWSGI startup / reload, but if you try to set a breakpoint in code blocks of your requests, I've found it to either skip over it, or hang entirely, without ever hitting it, and uWSGI shows a gateway error, after timeout.

Upvotes: 2

Views: 2384

Answers (1)

seaders
seaders

Reputation: 4096

The problem here, as far as I see it is exactly that last point, the debugger connects to uWSGI / the application process, which is not any of the individual request processes.

To solve this, from my situation, it needed 2 things changed, 1 of which is the uWSGI configuration for my app. Our production file looks something like

[uwsgi]
...
master = true
enable-threads = true
processes = 5

But here, to give the debugger (and us) an easy time to connect to the request process, and stay connected, we change this to

[uwsgi]
...
master = true
enable-threads = false
processes = 1

Make it the master, disable threads, and limit it to only 1 process - http://uwsgi-docs.readthedocs.io/en/latest/Options.html

Then, in the startup python file, instead of setting the debugger to connect when the entire flask app starts, you set it to connect in a function decorated with the handy flask function, before_first_request http://flask.pocoo.org/docs/0.12/api/#flask.Flask.before_first_request, so the startup script changes to something like,

import sys
import wsgi_configuration_module

sys.path.append('pycharm-debug.egg')
import pydevd

app = wsgi_configuration_module.app


@app.before_first_request
def before_first_request():
    pydevd.settrace('localhost', port=11211,
                    stdoutToServer=True, stderrToServer=True,
                    suspend=False)
    print 'connected'

#

So now, you've limited uWSGI to no threads, and only 1 process to limit the chance of any mixup with them and the debugger, and set pydevd to only connect before the very first request. Now, the debugger connects (for me) successfully once, at the first request in this function, prints 'connected' only once, and from then on breakpoints connect in any of your request endpoint functions without issue.

Upvotes: 3

Related Questions