Remember once gunicorn started flask experience problems

Error phenomenon:

gunicorn + nginx + flask deployment project, the deployment process is no problem, the project also started normally, but once access interface, the error will be:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/sync.py", line 135, in handle
    self.handle_request(listener, req, client, addr)
  File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/sync.py", line 176, in handle_request
    respiter = self.wsgi(environ, resp.start_response)
TypeError: __call__() takes from 1 to 2 positional arguments but 3 were given

But I run through runserver, it is no problem, outside the network can access.

So the question lies in the wsgi docking gunicorn and the flask.

When the gunicorn way to start is gunicorn [options] file: app

I think a lot of other areas, try a lot, not solved, then stared at these words thought for a twenty minutes ........ ah ....... may be the reason:

Direct start, it will run directly through the terminal runserver file to start, and ultimately provide a service that app (that is, instances of the flask)

I for database migration, the startup file is registered objects flask-script, and finally start actually flask-script object that provides is some command line stuff like, simply put, is a command line extension, not database migration using the command line when no use (at least so it seemed to me white).

This idea came out of.

gunicorn it means service agents to handle high concurrent, coroutine / thread is provided by way of multi-process / concurrent access, so gunicorn flask proxy is an object that is instantiated flask of APP.

My startup file code is probably as follows:

from projects import APP, db
from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager

manage = Manager(APP)
migrate = Migrate(app=APP, db=db)
manage.add_command('db', MigrateCommand)

if __name__ == '__main__':
    manage.run()

The mistake is that I will provide examples of flask-script to the gunicorn, which led to the gunicorn received parameter is not a standard wsgi parameters, error.

The solution is simple: APP (for here) to gunicorn agent just fine.

So gunicorn start command changed:

1 gunicorn -D -w 3 -t 300 -b 0.0.0.0:5000 manage:APP

If necessary, add the configuration log, the best personal advice plus journaling, which is the most direct data processing issues

gunicorn -D --error-logfile=/logs/gunicorn.log --pid=/logs/gunicorn.pid --access-logfile=/logs/access.log -w 3 -t 300 -b 0.0.0.0:5000 manage:APP

 

So the cause of this problem is that the agreement is not wsgi standard execution, the proxy server is a proxy server APP, but I have not noticed this.

The following is a flask-script operating mechanism when the terminal of the direct runserver:

I As shown in the code above, Manage is an example of a flask-script, when executed Python manage, this example will execute the run () method

    def run(self, commands=None, default_command=None):
        """
        Prepares manager to receive command line input. Usually run
        inside "if __name__ == "__main__" block in a Python script.

        :param commands: optional dict of commands. Appended to any commands
                         added using add_command().

        :param default_command: name of default command to run if no
                                arguments passed.
        """

        if commands:
            self._commands.update(commands)

        # Make sure all of this is Unicode
        argv = list(text_type(arg) for arg in sys.argv)
        if default_command is not None and len(argv) == 1:
            argv.append(default_command)

        try:
            result = self.handle(argv[0], argv[1:])
        except SystemExit as e:
            result = e.code

        sys.exit(result or 0)

The method described above performs handle () and then through a series of methods, passing execute the following code:

    def add_default_commands(self):
        """
        Adds the shell and runserver default commands. To override these,
        simply add your own equivalents using add_command or decorators.
        """

        if "shell" not in self._commands:
            self.add_command("shell", Shell())
        if "runserver" not in self._commands:
            self.add_command("runserver", Server())

The above code will call the method flask-script add two command objects, among them we are very familiar with the runserver, the command executes Server () object, call as follows:

    def __call__(self, app, host, port, use_debugger, use_reloader,
                 threaded, processes, passthrough_errors, ssl_crt, ssl_key):
        # we don't need to run the server in request context
        # so just run it directly

        if use_debugger is None:
            use_debugger = app.debug
            if use_debugger is None:
                use_debugger = True
                if sys.stderr.isatty():
                    print("Debugging is on. DANGER: Do not allow random users to connect to this server.", file=sys.stderr)
        if use_reloader is None:
            use_reloader = use_debugger

        if None in [ssl_crt, ssl_key]:
            ssl_context = None
        else:
            ssl_context = (ssl_crt, ssl_key)

        app.run(host=host,
                port=port,
                debug=use_debugger,
                use_debugger=use_debugger,
                use_reloader=use_reloader,
                threaded=threaded,
                processes=processes,
                passthrough_errors=passthrough_errors,
                ssl_context=ssl_context,
                **self.server_options)

Here is very clear, and in the implementation of python manage.py runserver, run method if the command is not flask-script provided by other commands, it would execute flask instance, in essence, is the Flask (__ name __). Run ( )

The flask-script is to monitor have not received your order.

Though the APP flask-script agent will flask, the flask-script object but not the same flask instance, it must also be provided to gunicorn flask to be obtained app

 

Guess you like

Origin www.cnblogs.com/haiton/p/11295495.html