In the heroku tutorial, there is a piece of code
hello.py
import os
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello World!'
and a Procfile:
web: gunicorn hello:app --log-file=-
The part that's really confusing is the hello:app
part; does hello
refer to the hello()
function or the hello.py script? Depending on the meaning of that, what does the whole Procfile statement mean?
tl;dr: hello
refers to hello.py
and app
refers to app = Flask(__name__)
The mentioned Heroku tutorial is no more available, however Gunicorn's doc gives a good minimal example :
Example with the test app:
def app(environ, start_response): """Simplest possible application object""" data = b'Hello, World!\n' status = '200 OK' response_headers = [ ('Content-type', 'text/plain'), ('Content-Length', str(len(data))) ] start_response(status, response_headers) return iter([data])
You can now run the app with the following command:
$ gunicorn --workers=2 test:app
Let's try, my test-directory looks like this :
(.venv) 14:41 ~/testgunicorn % tree
.
├── requirements.txt
└── testpkg
├── __init__.py
└── testfile.py
__init__.py
:
from flask import Flask
from .testfile import app
testfile.py
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def app(environ, start_response):
"""Simplest possible application object"""
data = b'Hello, World!\n'
status = '200 OK'
response_headers = [
('Content-type', 'text/plain'),
('Content-Length', str(len(data)))
]
start_response(status, response_headers)
return iter([data])
Wrong calling :
(.venv) 14:41 ~/testgunicorn % gunicorn testfile:app
[2018-08-24 14:41:44 +0200] [27248] [INFO] Starting gunicorn 19.9.0
[2018-08-24 14:41:44 +0200] [27248] [INFO] Listening at: http://127.0.0.1:8000 (27248)
[2018-08-24 14:41:44 +0200] [27248] [INFO] Using worker: sync
[2018-08-24 14:41:44 +0200] [27251] [INFO] Booting worker with pid: 27251
[2018-08-24 14:41:44 +0200] [27251] [ERROR] Exception in worker process
Traceback (most recent call last):
File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
worker.init_process()
File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/workers/base.py", line 129, in init_process
self.load_wsgi()
File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/workers/base.py", line 138, in load_wsgi
self.wsgi = self.app.wsgi()
File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/app/base.py", line 67, in wsgi
self.callable = self.load()
File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 52, in load
return self.load_wsgiapp()
File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
return util.import_app(self.app_uri)
File "~/testgunicorn/.venv/lib/python3.6/site-packages/gunicorn/util.py", line 350, in import_app
__import__(module)
ModuleNotFoundError: No module named 'testfile'
[2018-08-24 14:41:44 +0200] [27251] [INFO] Worker exiting (pid: 27251)
[2018-08-24 14:41:44 +0200] [27248] [INFO] Shutting down: Master
[2018-08-24 14:41:44 +0200] [27248] [INFO] Reason: Worker failed to boot.
zsh: exit 3 gunicorn testfile:app
Good callings :
(.venv) 14:43 ~/testgunicorn % gunicorn testpkg:app
[2018-08-24 14:43:56 +0200] [27302] [INFO] Starting gunicorn 19.9.0
[2018-08-24 14:43:56 +0200] [27302] [INFO] Listening at: http://127.0.0.1:8000 (27302)
[2018-08-24 14:43:56 +0200] [27302] [INFO] Using worker: sync
[2018-08-24 14:43:56 +0200] [27305] [INFO] Booting worker with pid: 27305
^C
(…)
(.venv) 15:03 ~/testgunicorn % cd testpkg
(.venv) 15:03 fred@susa ~/git/ocp7/testpkg % gunicorn testfile:app
[2018-08-24 15:03:22 +0200] [27494] [INFO] Starting gunicorn 19.9.0
[2018-08-24 15:03:22 +0200] [27494] [INFO] Listening at: http://127.0.0.1:8000 (27494)
[2018-08-24 15:03:22 +0200] [27494] [INFO] Using worker: sync
[2018-08-24 15:03:22 +0200] [27497] [INFO] Booting worker with pid: 27497
^C
(…)
Then for this Procfile
:
web: gunicorn hello:app --log-file=-
Does hello refer to the hello() function or the hello.py script?
To the hello.py
script
Depending on the meaning of that, what does the whole Procfile statement mean?
Heroku's Procfile format documentation says :
A Procfile declares its process types on individual lines, each with the following format:
<process type>: <command>
<process type>
is an alphanumeric name for your command, such as web, worker, urgentworker, clock, and so on.<command>
indicates the command that every dyno of the process type should execute on startup, such as rake jobs:work.
The --logfile=-
option seems to be deprecated, I did not find anything about it in documentation and if I use it I get this error :
(.venv) 15:34 ~/testgunicorn % heroku local web
[WARN] No ENV file found
15:34:30 web.1 | usage: gunicorn [OPTIONS] [APP_MODULE]
15:34:30 web.1 | gunicorn: error: unrecognized arguments: --logfile=-
15:34:30 web.1 Exited with exit code 2
According to this answer it was an option for logging in Heroku's stdout.
The ProcFile contains the command line for starting your application on heroku. The full documentation can be found here: https://devcenter.heroku.com/articles/procfile
In this case it is telling heroku to use the app variable (your constructed flask app) in the hello module with gunicorn and to start a web process (one that can handle http requests). There are other process types you can specify such as background workers.
Your flask application object is a WSGI application, and can be run using any WSGI server. Gunicorn is just one of the choices on heroku.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With