'Flask config import fails on Heroku

My application works fine when run locally (with flask run), and it also works on Heroku when the app.config.from_object(config.DevelopmentConfig) is commented out. However, gunicorn can't find the config file when deployed on Heroku. (I can't try gunicorn locally on my Windows machine.)

__init__.py

from flask import Flask

app = Flask(__name__)
app.config.from_object('config.DevelopmentConfig')

from app import views

Procfile

web: gunicorn app:app

Directory structure

My config.py is the project root, although I did add a copy in the app directory to no avail.

/ProjectRoot
  config.py
  /app
    __init.py__
    views.py
    /static
    /templates

Heroku log

The error log with time stamps removed:

: [2016-08-23 01:18:51 +0000] [9] [INFO] Worker exiting (pid: 9)
:
: Original exception:
:
: Process exited with status 3
:     self.wsgi = self.app.wsgi()
:   File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
:     self.callable = self.load()
:     self.load_wsgi()
:   File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/workers/base.py", line 136, in load_wsgi
:     worker.init_process()
: [2016-08-23 01:18:51 +0000] [10] [ERROR] Exception in worker process
: Traceback (most recent call last):
:   File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/arbiter.py", line 557, in spawn_worker
:   File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/workers/base.py", line 126, in init_process
: ImportStringError: import_string() failed for 'config.DevelopmentConfig'. Possible reasons are:
:
:   File "/app/.heroku/python/lib/python2.7/site-packages/werkzeug/utils.py", line 443, in import_string
:     obj = import_string(obj)
: State changed from starting to up
:     app.config.from_object('config.DevelopmentConfig')
:   File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
:     return self.load_wsgiapp()
:   File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
:     return util.import_app(self.app_uri)
:   File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/util.py", line 357, in import_app
:     __import__(module)
:   File "/app/app/__init__.py", line 10, in <module>
:   File "/app/.heroku/python/lib/python2.7/site-packages/flask/config.py", line 163, in from_object
:   File "/app/.heroku/python/lib/python2.7/site-packages/werkzeug/utils.py", line 436, in import_string
:     raise ImportError(e)
: - missing __init__.py in a package;
: - package or module path not included in sys.path;
: - duplicated package or module name taking precedence in sys.path;
: - missing module, class, function or variable;
:
: Debugged import:
:
:
: ImportError: 'module' object has no attribute 'DevelopmentConfig'
: Original exception:
: - 'config' found in '/app/config.pyc'.
:
: [2016-08-23 01:18:51 +0000] [10] [INFO] Worker exiting (pid: 10)
: [2016-08-23 01:18:51 +0000] [3] [INFO] Shutting down: Master
: [2016-08-23 01:18:51 +0000] [3] [INFO] Reason: Worker failed to boot.
:     sys.exc_info()[2])
: - 'config.DevelopmentConfig' not found.
: State changed from up to crashed

Update I changed config too foo and, much to my surprise, it seemed to work. So maybe there is a duplicate in the path. I will experiment with it some more before writing up an answer.



Solution 1:[1]

Another possible error that I made was putting the config.py file in a subpackage when it should have been in the root directory. I had:

.
??? cms
?   ??? api
?   ?   ??? __init__.py
?   ?   ??? routes.py
?   ??? __init__.py
?   ??? studio
?       ??? app.py
?       ??? config.py
?       ??? forms.py
?       ??? __init__.py
?       ??? main.py
?       ??? models.py
?       ??? routes.py
?       ??? uploader.py
??? Contributing.md
??? LICENSE
??? README.md
??? requirements.txt
??? run


So I moved the config.py file to the root, and it now looks like this:

.
??? cms
?   ??? api
?   ?   ??? __init__.py
?   ?   ??? routes.py
?   ??? __init__.py
?   ??? studio
?       ??? app.py
?       ??? forms.py
?       ??? __init__.py
?       ??? main.py
?       ??? models.py
?       ??? routes.py
?       ??? uploader.py
??? config.py
??? Contributing.md
??? LICENSE
??? README.md
??? requirements.txt
??? run

Works!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dev Elie