3

I'm trying to figure out how to easily switch between debugging my Flask application with the Flask (Werkzeug) debugger and using PyCharm's debugger. I've gotten as far as having two PyCharm run configurations

  1. one that I invoke with "Run" and --debug flag supplied to the application script; and
  2. one that I invoke with "Debug" and a --pydebug flag supplied to the application script

with the flags supported in my application script with"

if __name__ == "__main__":

    import argparse
    parser = argparse.ArgumentParser(description='Runs Web application with options for debugging')
    parser.add_argument('-d', '--debug', action='store_true', 
                        dest='debug_mode', default=False,
                        help='run in Werkzeug debug mode')
    parser.add_argument('-p', '--pydebug', action='store_true') 
                        dest='debug_pycharm', default=False,
                        help='for use with PyCharm debugger')

    cmd_args = parser.parse_args()
    app_options = dict()

    app_options["debug"] = cmd_args.debug_mode or cmd_args.debug_pycharm
    if cmd_args.debug_pycharm:
        app_options["use_debugger"] = False
        app_options["use_reloader"] = False

    application.run(**app_options)

This works, and meets the requirement that I don't need to edit any code to deploy to a server; but I'm not sure it's the best approach. For one thing I need to remember that the second configuration is meant to be launched with "Debug" (not "Run") while the first is meant to be launched with "Run" (not "Debug") in PyCharm.

Is there a better approach to supporting these two approaches to debugging in PyCharm, using either some feature of PyCharm (e.g. that allows me to detect when "Debug" has been invoked rather than "Run") or smarter use of Flask's features.

2 Answers 2

4

A very easy way to check if your application is running under the PyCharm debugger is:

'pydevd' in sys.modules
Sign up to request clarification or add additional context in comments.

Comments

1

On Pycharm Professional 2020.1 there is now a Flask Server run/debug configuration choice and I got it working with the following inputs (stops at breakpoints, step in step over, etc).

enter image description here

That is for a project structured like this:

enter image description here

and main.py that looks like this:


import warnings
from flask import Flask
from flask_mongoengine import MongoEngine
from flask_script import Server, Manager
from flask_bootstrap import Bootstrap
from flask_user import UserManager
from flask_mail import Mail
from flask_wtf.csrf import CSRFProtect

# for importing module from parent dir
import os, sys, inspect
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parent_dir = os.path.dirname(current_dir)
sys.path.insert(0, parent_dir)
import cnf.settings as settings
import cnf.scripts.scripts as scripts


# pymongo has issues...
warnings.filterwarnings("ignore", category=DeprecationWarning, module='mongoengine')

#instantiate Flask extensions
#csrf_protect = CSRFProtect()
#mail = Mail()

config = settings.config


def setup_app(config_name, extra_config_settings={} ):
    app = Flask(
        __name__, # special variable that gets string val of __main__ when executing script
        #static_url_path='',
        #static_folder='static',
        static_folder=settings.Config.STATIC_FOLDER,
        template_folder=settings.Config.TEMPLATE_FOLDER,
    )

    app.config.from_object(config[config_name])
    # load extra settings from extra config settings param
    app.config.update(extra_config_settings)

    with app.app_context():
        app.db = MongoEngine(app)

        #csrf_protect.init_app(cnf)
        app.CSRFProtect = CSRFProtect(app)
        #register blueprints
        from cnf.views import register_blueprints
        register_blueprints(app)

        # Define bootstrap is hidden_field for flask bootstrap's
        # bootstrap wtf.html
        from wtforms.fields import HiddenField

        def is_hidden_field_filter(field):
            return isinstance(field, HiddenField)

        app.jinja_env.globals['bootstrap_is_hidden_field'] = is_hidden_field_filter
        app.mail = Mail(app)
        #init_email_error_handler(cnf)

        # setup Flask-User to handle user account related forms
        from cnf.models.user_models import User
        user_manager = UserManager(app, app.db, User)

        @app.context_processor
        def context_processor():
            return dict(user_manager=user_manager)

        app.bootstrap = Bootstrap(app)
        '''
        app.manager = Manager(app)
        app.manager.add_command(
            'runserver',
            Server(
                host=app.config['FLASK_BIND'],
                port=app.config['FLASK_PORT']
            )
        )
        '''
        # import csv files
        #app.manager.add_command('import', scripts.Import())
        #Importer = scripts.Import()
        #Importer.run()

    return app

'''
def main():  # pragma: no cover
    app = setup_app('default') #with default dev configs

    # Import your views!
    with app.app_context():
        import cnf.views
    app.manager.run()

'''


if __name__ == "__main__":  # pragma: no cover
    #add_path()
    app = setup_app('default')

    # Import your views!
    with app.app_context():
        pass
    app.run()
    #app.manager.run()


# python cnf/main.py runserver

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.