How to use Python main() function in GAE (Google App Engine)?
<p>I'd like to use a <code>main()</code> function in my GAE code <br>(note: the code below is just a minimal demonstration for a much larger program, hence the need for a <code>main()</code>).</p>

<p>If I use the following code, it performs as expected:</p>

<pre><code>import webapp2

class GetHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('in GET')

class SetHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('in SET')

app = webapp2.WSGIApplication([
    ('/get',    GetHandler),
    ('/set',    SetHandler),
], debug=True)
</code></pre>

<p>where my <code>app.yaml</code> is:</p>

<pre><code>runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /.*
  script: main.app
</code></pre>

<p><strong>However</strong>, I cannot figure out how to implement a <code>main()</code> function, and still have <code>app</code> act as it does in the code at the top. Namely, the following:</p>

<pre><code># with main()
import webapp2

class GetHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('in GET')

class SetHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('in SET')

def main():
    app = webapp2.WSGIApplication([
        ('/get',    GetHandler),
        ('/set',    SetHandler),
    ], debug=True)

if __name__ == '__main__':
    main()
</code></pre>

<p>gives the following error for <code>http://localhost:8080/get:</code></p>

<pre><code>$ dev_appserver.py .
INFO     2016-10-17 11:29:30,962 devappserver2.py:769] Skipping SDK update check.
INFO     2016-10-17 11:29:31,059 api_server.py:205] Starting API server at: http://localhost:45865
INFO     2016-10-17 11:29:31,069 dispatcher.py:197] Starting module "default" running at: http://localhost:8080
INFO     2016-10-17 11:29:31,073 admin_server.py:116] Starting admin server at: http://localhost:8000
ERROR    2016-10-17 11:29:37,461 wsgi.py:263] 
Traceback (most recent call last):
  File "/home/.../sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 240, in Handle
    handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
  File "/home/.../sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 302, in _LoadHandler
    raise err
ImportError: &lt;module 'main' from '/home/.../main.pyc'&gt; has no attribute app
INFO     2016-10-17 11:29:37,496 module.py:788] default: "GET /get HTTP/1.1" 500 -
</code></pre>

<h2>Edit 1</h2>

<p>Trying:</p>

<pre><code># with main()
import webapp2

app = webapp2.RequestHandler()

class GetHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('in GET')

class SetHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('in SET')

def main():
    global app
    app = webapp2.WSGIApplication([
        ('/get',    GetHandler),
        ('/set',    SetHandler),
    ], debug=True)
    return app

if __name__ == '__main__':
    app = main()
</code></pre>

<p>Results in:</p>

<pre><code>INFO     2016-10-17 12:30:34,751 module.py:402] [default] Detected file changes:
  /home/openstack/googleAppEngine/fastsimon/task2/task2_with_main/main.py
ERROR    2016-10-17 12:30:42,328 wsgi.py:279] 
Traceback (most recent call last):
  File "/home/openstack/googleAppEngine/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 267, in Handle
    result = handler(dict(self._environ), self._StartResponse)
TypeError: 'RequestHandler' object is not callable
INFO     2016-10-17 12:30:42,335 module.py:788] default: "GET /get HTTP/1.1" 500 -
</code></pre>

<p>GAE apps are not designed to be standalone apps, a <code>main()</code> function doesn't make a lot of sense for them.</p>

<p>Basically GAE apps are really just collections of handler code and rules/configurations designed to extend and customize the behaviour of the generic GAE infra/sandbox code so that it behaves your app. You can see that from your backtrace - other code is invoking your handler code (and the stack before reaching your code can be <em>a lot deeper</em> than that).</p>

<p>In your particular case the <code>app</code> variable <strong>must</strong> be a global in <code>main.py</code> to match the <code>script: main.app</code> config line in the <code>app.yaml</code> config file. This is what the traceback is about.</p>

<p>As for organizing the code for huge apps, there are other ways of doing it:</p>

<ul>
<li><p>splitting the app in multiple <a href="https://cloud.google.com/appengine/docs/python/an-overview-of-app-engine#services_the_building_blocks_of_app_engine" rel="nofollow">modules/services</a>, each with their own <code>app.yaml</code> config file. For example: <a href="http://stackoverflow.com/questions/34110178/can-a-default-module-in-a-google-app-engine-app-be-a-sibling-of-a-non-default-mo">Can a default module in a Google App Engine app be a sibling of a non-default module in terms of folder structure?</a></p></li>
<li><p>splitting a service/module into multiple "scripts" - primary entry points into the <code>app.yaml</code> file similar to your <code>main.py</code> file, each with their own <code>app</code> config` - which really are just mappers between routes and handlers. For example: <a href="http://stackoverflow.com/questions/39349590/app-engine-throws-404-not-found-for-any-path-but-root">App Engine throws 404 Not Found for any path but root</a></p></li>
<li><p>splitting the handlers for one <code>app</code> mapper into multiple files, using webapp2's lazy loaded handler technique. Examples:</p>

<ul>
<li><a href="http://stackoverflow.com/questions/33453441/app-engine-few-big-scripts-or-many-small-ones/33457227#33457227">App Engine: Few big scripts or many small ones?</a></li>
<li><a href="http://stackoverflow.com/questions/34635012/what-determines-start-up-time-of-dynamic-instance-and-can-it-vary-between-weeks/34637044#34637044">What determines start up time of dynamic instance and can it vary between weeks if code is same</a> </li>
</ul></li>
</ul>

<p>In an extreme case a <code>main.py</code> file could contain <em>just</em> the <code>app</code> variable - that is really the only requirement.</p>

python python-2.7 google-app-engine main wsgi