What is the difference between the two ways for launching flask?

Question:

I have used two ways to launch a Flask application

  1. use python app.py directly

  2. use gunicorn -w 1 -b localhost:5000 app:app

Then I printed the call stacks,I know the second way is better because it uses a wsgi server and can be used in a production environment, but I still can not understand what is the deep difference through the call stack.

Can anyone tell me what is the difference between those two ways?

1

File "/usr/lib/python3.6/threading.py", line 884, in _bootstrap
self._bootstrap_inner()
File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/usr/lib/python3.6/threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3.6/socketserver.py", line 651, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib/python3.6/socketserver.py", line 361, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python3.6/socketserver.py", line 721, in __init__
self.handle()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/werkzeug/serving.py", line 326, in handle
rv = BaseHTTPRequestHandler.handle(self)
File "/usr/lib/python3.6/http/server.py", line 418, in handle
self.handle_one_request()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/werkzeug/serving.py", line 361, in handle_one_request
return self.run_wsgi()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/werkzeug/serving.py", line 303, in run_wsgi
execute(self.server.app)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/werkzeug/serving.py", line 291, in execute
application_iter = app(environ, start_response)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 2328, in __call__
return self.wsgi_app(environ, start_response)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 2311, in wsgi_app
response = self.full_dispatch_request()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 1832, in full_dispatch_request
rv = self.dispatch_request()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 1818, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "app.py", line 10, in hello
traceback.print_stack()

2

File "/home/wangxu/pyApp/flaskApp/bin/gunicorn", line 11, in <module>
sys.exit(run())
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 61, in run
WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/app/base.py", line 223, in run
super(Application, self).run()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/app/base.py", line 72, in run
Arbiter(self).run()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/arbiter.py", line 203, in run
self.manage_workers()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/arbiter.py", line 545, in manage_workers
self.spawn_workers()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/arbiter.py", line 616, in spawn_workers
self.spawn_worker()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
worker.init_process()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/base.py", line 134, in init_process
self.run()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 124, in run
self.run_for_one(timeout)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 68, in run_for_one
self.accept(listener)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 30, in accept
self.handle(listener, client, addr)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 135, in handle
self.handle_request(listener, req, client, addr)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 176, in handle_request
respiter = self.wsgi(environ, resp.start_response)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 2328, in __call__
return self.wsgi_app(environ, start_response)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 2311, in wsgi_app
response = self.full_dispatch_request()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 1832, in full_dispatch_request
rv = self.dispatch_request()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 1818, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/wangxu/pyApp/flaskApp/app.py", line 10, in hello
s = traceback.print_stack()
Asked By: Xu Wang

||

Answers:

  • One starts 1 process, another can start more processes, if you specify.
  • One starts an app that directly listens to request, another starts wsgi worker(s) that run behind gunicorn, or could run behind another wsgi-compliant server, e.g. a web-server that also terminates SSL.

There are more differences, but the above seem to be key differences.

Answered By: 9000
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.