Home / APIs / Figuring out Python webapp2 and WSGI on and off the GAE

Figuring out Python webapp2 and WSGI on and off the GAE

Okay, I stand at a cross-roads, in my career, in my personal life with a second child on the way, and generally in my life as I decide on the type of professional and the type of daddy I’m going to be. Nothing exemplifies this as clearly as my doing development work for Google Glasses. I have to plow my way through some learning-while-replatforming challenges.

Okay, so much of what’s going on now is picking apart webapp2 and the simpler, but completely compatible webapp framework. Do everything so that it’s BOTH on the Google App Engine AND Levinux. This way, you will really understand things. You need to look through things, and look truly closely, and understand what you’re looking at!

Okay, this is like just approaching Active Server Page or Apache2/mod_python for the very first time. The fundamentals need to be groked. Everything else builds on that. I have to spot the super-valuable little nuggets like:

The WSGIApplication constructor takes a list of pairs (tuples) that map URL paths to RequestHandler classes.

Wow, is that an important bit of info! Given the 3 different contexts of running program code from my prior post and journal entry, HERE is where we begin to get exposed to the webapp framework and its conventions. How precisely does YOUR CODE get run in this webserver context?

Well, the answer is that the traditional “main” function in Python, which traditionally gets run with a function at the bottom of a program that looks like this:

  1. if __name__ == '__main__':
  2.   main()
if __name__ == '__main__':
  main()

That’s just a super-common thing in Python. If the name of the scope I’m running in is __main__, then run a function called main. That’s just a Python-ism that you have to take at face value. There are different ways of achieving the same result. This is just what everyone does, and if you do it too, everyone will recognize it. So, that’s a familiar bit.

But now, inside the function called “main”, you might have one of two different possibilities based on whether or not you actually are on the Google App Engine or not. If you ARE, it looks like:

  1. def main():
  2.   from google.appengine.ext.webapp.util¬†import run_wsgi_app
  3.   run_wsgi_app(app)
def main():
  from google.appengine.ext.webapp.util import run_wsgi_app
  run_wsgi_app(app)

…but if you’re self-hosting (not on GAE), it looks like:

  1. def main():
  2.   from paste import httpserver
  3.   httpserver.serve(app, host='10.0.2.15', port='81')
def main():
  from paste import httpserver
  httpserver.serve(app, host='10.0.2.15', port='81')

Okay, so there’s a very clear step here of taking an object named “app” and making it get served. This is how YOUR PROGRAM gets put into the third execution context discussed – that of a webserver. Okay, here’s one of those magic, insightful phrases:

A WSGI application is passed a Python representation of an HTTP request by an application, and returns content which will normal eventually be rendered by a web browser.

Hmmmm. Okay, I’m starting to listen to the audio book, Managing Oneself, by Peter Drucker from the Harvard Business Review. Just like listening to Managing in a Time of Great Change during my Scala days, which helped so much. Am I going to be able to listen to this while I productively work? Hmmm, I think so. I will try. I will surely intersperse tidbits of wisdom into my daily journal as I go.

Where is my deficit right now? Understanding what’s going on in The Google App Engine with the Google Mirror API Quickstart examples. Steadfast focus on performance and results! Practice consistently the method of writing down what you expect of your actions.

Hmmmm. Okay, what I expect of my current actions are:

  1. Contributing to the delivery of the first Google Glass Glassware from my place of employment. Play an important enough role for my name to be associated with it, and frequently invoked.
  2. Actually understand fairly deeply, deeper than most, what’s going on in the Glassware. Be able to reproduce such an app on a platform OTHER THAN the Google App Engine, so that I do not actually rely on it.
  3. Actually become familiar with the Google App Engine way of doing things. Even though my gut makes me suspicious and contemptuous of yet another vendor lock-in platform antlion trap, have an open mind, and understand when such a platform is advantageous over the old way, and why.

Waste as little time as possible taking on work outside my area of specialty. Make sure that I’m starting from competent performance, and move onto star performer. Don’t move from incompetency to competency. It’s not an efficient use of time. Make sure I am well chosen for this rapid prototype position. Everything is off the beaten trail, which makes accelerating competency and shortcuts of leveraging well-known and practiced frameworks.

Sooooo…

The question I need to ask now is…

RECOGNIZE what’s going on in the main.py of the GAE Glass Quickstart examples VERSUS the other “hello world” examples of webapp2. List all three. Examine the differences. Start to dig down and ferret out your answers.

Here’s the main.py program from the GAE that handles OAuth 2 login and everything:

  1. __author__ = 'alainv@google.com (Alain Vongsouvanh)'
  2.  
  3. # Add the library location to the path import sys sys.path.insert(0, 'lib')
  4.  
  5. import webapp2
  6.  
  7. from attachmentproxy.handler import ATTACHMENT_PROXY_ROUTES
  8. from main_handler import MAIN_ROUTES
  9. from notify.handler import NOTIFY_ROUTES
  10. from oauth.handler import OAUTH_ROUTES
  11. from signout.handler import SIGNOUT_ROUTES
  12.  
  13. ROUTES = (
  14. ATTACHMENT_PROXY_ROUTES + MAIN_ROUTES + NOTIFY_ROUTES + OAUTH_ROUTES + SIGNOUT_ROUTES)
  15.  
  16. app = webapp2.WSGIApplication(ROUTES)
__author__ = 'alainv@google.com (Alain Vongsouvanh)'

# Add the library location to the path import sys sys.path.insert(0, 'lib')

import webapp2

from attachmentproxy.handler import ATTACHMENT_PROXY_ROUTES
from main_handler import MAIN_ROUTES
from notify.handler import NOTIFY_ROUTES
from oauth.handler import OAUTH_ROUTES
from signout.handler import SIGNOUT_ROUTES

ROUTES = (
ATTACHMENT_PROXY_ROUTES + MAIN_ROUTES + NOTIFY_ROUTES + OAUTH_ROUTES + SIGNOUT_ROUTES)

app = webapp2.WSGIApplication(ROUTES)

…and here is Hello World on the GAE…

  1. import webapp2
  2.  
  3. class MainPage(webapp2.RequestHandler):
  4.   def get(self):
  5.     self.response.headers['Content-Type'] = 'text/plain'
  6.     self.response.write('Hello, World!')
  7.  
  8. application = webapp2.WSGIApplication([
  9.   ('/', MainPage),
  10.   ], debug=True)
import webapp2

class MainPage(webapp2.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.write('Hello, World!')

application = webapp2.WSGIApplication([
  ('/', MainPage),
  ], debug=True)

…and here is the Hello World WITHOUT the GAE…

  1. import webapp2 as webapp from google.appengine.ext.webapp.util
  2. import run_wsgi_app
  3.  
  4. class HelloWorldHandler(webapp.RequestHandler):
  5.   def get(self):
  6.     self.response.out.write('Hello, World!')
  7.  
  8. app = webapp.WSGIApplication([
  9.   ('/', HelloWorldHandler),
  10.   ], debug=True)
  11.  
  12. def main():
  13.   run_wsgi_app(app)
  14.  
  15. if __name__ == '__main__':
  16.   main()
import webapp2 as webapp from google.appengine.ext.webapp.util
import run_wsgi_app

class HelloWorldHandler(webapp.RequestHandler):
  def get(self):
    self.response.out.write('Hello, World!')

app = webapp.WSGIApplication([
  ('/', HelloWorldHandler),
  ], debug=True)

def main():
  run_wsgi_app(app)

if __name__ == '__main__':
  main()

Study the differences between these!

Comments

comments

Previous
Next