This post talks about how I refactored a Flask application and subsequently ran into a gotcha with Google App Engine's defaults, and how to resolve it.

Backstory: I previously wrote about creating a Slack app in Python. At the time, the app was pretty small, so all of my logic went into a However, that's not good development practice, and the file became hard to read at 500 lines long. I also wanted to add in things like config files, as the list of things to configure was growing longer. So I decided it was time to restructure the entire application and abide more by conventions.

I followed the Flask docs on structuring larger applications. I created separated different kinds of logic, like route handling and error handling, into different files. My end result looked something like this:


Unfortunately, when I actually deployed it to GAE, it blew up. Specifically, the GAE logs had the following error:

"Traceback (most recent call last):
  File "/env/lib/python3.7/site-packages/gunicorn/", line 583, in spawn_worker
  File "/env/lib/python3.7/site-packages/gunicorn/workers/", line 104, in init_process
    super(ThreadWorker, self).init_process()
  File "/env/lib/python3.7/site-packages/gunicorn/workers/", line 129, in init_process
  File "/env/lib/python3.7/site-packages/gunicorn/workers/", line 138, in load_wsgi
    self.wsgi =
  File "/env/lib/python3.7/site-packages/gunicorn/app/", line 67, in wsgi
    self.callable = self.load()
  File "/env/lib/python3.7/site-packages/gunicorn/app/", line 52, in load
    return self.load_wsgiapp()
  File "/env/lib/python3.7/site-packages/gunicorn/app/", line 41, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/env/lib/python3.7/site-packages/gunicorn/", line 350, in import_app
ModuleNotFoundError: No module named 'main'"

Turns out that according to Google's docs, GAE looks for a in the application directory root containing a variable called app, which is the application. Since I switched to putting the app in myapp/, GAE couldn't find this anymore.

The suggested solution is to add a custom entrypoint to your app.yaml such as entrypoint: gunicorn -b :$PORT myapp:app. However, that didn't work for me. So what I did was to simply conform to what GAE wanted, and added a dummy which imports my application as app. The file only contains the following:

from myapp import app

And now my folder structure looks like this:


Maybe not the most elegant solution, but it got my app working on GAE.