How to use Flask-Script and Gunicorn

前端 未结 7 543
[愿得一人]
[愿得一人] 2020-12-02 12:39

I\'m working on on a Flask app using Flask\'s built in dev server. I start it using Flask-Script. I want to switch to using Gunicorn as the web server. To do so, do I nee

相关标签:
7条回答
  • 2020-12-02 13:09

    I wrote a better version of GunicornServer based on Sean Lynch's, the command now accept all gunicorn's arguments

    from yourapp import app
    from flask.ext.script import Manager, Command, Option
    
    class GunicornServer(Command):
        """Run the app within Gunicorn"""
    
        def get_options(self):
            from gunicorn.config import make_settings
    
            settings = make_settings()
            options = (
                Option(*klass.cli, action=klass.action)
                for setting, klass in settings.iteritems() if klass.cli
            )
            return options
    
        def run(self, *args, **kwargs):
            from gunicorn.app.wsgiapp import WSGIApplication
    
            app = WSGIApplication()
            app.app_uri = 'manage:app'
            return app.run()
    
    manager = Manager(app)
    manager.add_command("gunicorn", GunicornServer())
    
    0 讨论(0)
  • 2020-12-02 13:09

    Flask actually has docs to run Gunicorn here.

    You have to remember that Gunicorn is a WSGI server with some niceties.

    0 讨论(0)
  • 2020-12-02 13:14

    Thanks to @menghan's solution and @OutOfFoodException improvement. But remember that for gunicorn=20.0.4 for binding server socket using -b, --bind option. And result command for me was like that:

    python3 manage.py gunicorn -b 0.0.0.0:5000
    
    from yourapp import app
    from flask.ext.script import Manager, Command, Option
    
    class GunicornServer(Command):
        """Run the app within Gunicorn"""
    
        def get_options(self):
            from gunicorn.config import make_settings
    
            settings = make_settings()
            options = (
                Option(*klass.cli, action=klass.action)
                for setting, klass in settings.iteritems() if klass.cli
            )
            return options
    
        def run(self, *args, **kwargs):
            from gunicorn.app.wsgiapp import WSGIApplication
    
            app = WSGIApplication()
            app.app_uri = 'manage:app'
            return app.run()
    
    manager = Manager(app)
    manager.add_command("gunicorn", GunicornServer())
    
    0 讨论(0)
  • 2020-12-02 13:16

    Based the answer of the Sean, I also wrote a version more preferred to me.

    @manager.option('-h', '--host', dest='host', default='127.0.0.1')
    @manager.option('-p', '--port', dest='port', type=int, default=6969)
    @manager.option('-w', '--workers', dest='workers', type=int, default=3)
    def gunicorn(host, port, workers):
        """Start the Server with Gunicorn"""
        from gunicorn.app.base import Application
    
        class FlaskApplication(Application):
            def init(self, parser, opts, args):
                return {
                    'bind': '{0}:{1}'.format(host, port),
                    'workers': workers
                }
    
            def load(self):
                return app
    
        application = FlaskApplication()
        return application.run()
    

    you can run the gunicorn using command like thispython manager.py gunicorn

    0 讨论(0)
  • 2020-12-02 13:18

    Based on menghan's answer, receive all arguments from Application config.

    from flask_script import Command, Option
    
    
    class GunicornApp(Command):
    
        def get_options(self):
            from gunicorn.config import make_settings
    
            settings = make_settings()
            options = (
                Option(*klass.cli, dest=klass.name, default=klass.default)
                for setting, klass in settings.items() if klass.cli
            )
            return options
    
        def __call__(self, app=None, *args, **kwargs):
    
            from gunicorn.app.base import Application
            class FlaskApplication(Application):
                def init(self, parser, opts, args):
                    return kwargs
    
                def load(self):
                    return app
    
            FlaskApplication().run()
    
    0 讨论(0)
  • 2020-12-02 13:21

    I will elaborate further on the answer by @NinjaDQ. If you want to use app_uri attribute for defining for example the flask application configuration file and custom command line arguments at the same time, you need to use WSGIApplication. The problem is that this application overrides the command line arguments thus it is necessary to ignore the sys.argv.

            from gunicorn.app.base import Application
    
            class FlaskApplication(Application):
                def init(self, parser, opts, args):
                    return {
                        "bind": "{0}:{1}".format(host, port),
                        "workers": 4
                    }
    
                def chdir(self):
                    # chdir to the configured path before loading,
                    # default is the current dir
                    os.chdir(self.cfg.chdir)
    
                    # add the path to sys.path
                    sys.path.insert(0, self.cfg.chdir)
    
                def load_wsgiapp(self):
                    self.chdir()
    
                    # load the app
                    return util.import_app(self.app_uri)
    
                def load(self):
                    return self.load_wsgiapp()
    
            # Important! Do not pass any cmd line arguments to gunicorn
            sys.argv = sys.argv[:2]
    
            wsgi_app = FlaskApplication()
            wsgi_app.app_uri = "manage:create_app('{0}')".format(config_file)
    
            return wsgi_app.run()
    
    0 讨论(0)
提交回复
热议问题