Deploying web2py to Google App Engine

Search for TODO: in this chapter

There are two kinds of deployment to the Google App Engine: Locally, using a web server running as localhost on your development machine, and in App Engine's cloud servers.

Deploying locally is normally faster and lets you make mistakes before you go live. It is also necessary to build database indexes.

This chapter shows how to run web2py itself on Google App Engine, both locally and in the cloud. Web2py's sample GAE configuration files default to the familiar web2py welcome app.

When you deploy your app, you also deploy web2py itself

Your app consists of a set of subdirectories under web2py/applications/your_app.

The web2py directory tree may look complicated, but it's actually a fairly small framework consisting of a couple megabytes of source code in a well-structured directory tree. In practice, remember it's just a program--you launch it as you would any other Python program, for example:

# Just illustrating. Don't do this now
$ cd /usr/local/web2py
$ python web2py.py

Your app will be in a directory tree of its own in the location web2py/applications/your_app.

Google App Engine apps are just files that get served

Deploying a directory tree to GAE results in something a little gross on the Google side of things. It's just a huge mass of files in a single directory. Those get served by GAE when requested.

The directory tree structure is preserved only because slashes (or in Windows, backslashes) are legal filenames in GAE's own file system.

Deploying web2py locally using Google App Engine

Your first job is to run web2py locally the GAE way. You must do this before deploying it to GAE.

Recall that to run web2py locally you need a webserver running on your development machine. Instead of web2py's built-in Rocket server, you'll be using GAE's. Let's get web2py running locally using GAE deployment tools.

  • Make sure you're in your web2py directory.
$ cd /usr/local/web2py
  • Run web2py using the -G GAE option to generate the proper configuration files and place them in the web2py directory:
$ python web2py.py -G GAE
Your GAE app name: tomcampbell

This generates the files app.yaml and gaehandler.py. If you do it more than once you'll get this error message:

app.yaml already exists in the web2py folder
gaehandler.py already exists in the web2py folder

TODO: Explain what files are generated

TODO: Explain app name unless that happened early, which probably should be the case

TODO: Replace tomcampbell with better example name

This results in the creation of two files GAE needs: app.yaml and gaehandler.py.

  • Run dev_appserver.py:
$ dev_appserver.py ../web2py
# I think it may actually be:
# dev_appserver.py ../web2py --mysql_user=sampleuser --mysql_password=foo

Open your browser and visit this address: http://localhost:8080/welcome/default/index:

Screen shot of the web2py welcome app running locally

Deploying web2py to the cloud

We've seen web2py running locally using GAE. It's time to get that baby on the Web! Use appcfg.py to copy the files to up the cloud

$ appcfg.py update ../web2py

The output looks something like this

09:38 PM Application: tomcampbell; version: 1
09:38 PM Host: appengine.google.com
09:38 PM 
Starting update of app: tomcampbell, version: 1
09:38 PM Getting current resource limits.
09:38 PM Scanning files on local disk.
Could not guess mimetype for applications/welcome/static/fonts/glyphicons-halflings-regular.woff2.  Using application/octet-stream.
09:38 PM Scanned 500 files.
Could not guess mimetype for applications/welcome/static/fonts/glyphicons-halflings-regular.woff2.  Using application/octet-stream.
09:38 PM Cloning 195 static files.
09:38 PM Cloning 496 application files.
09:38 PM Uploading 43 files and blobs.
09:38 PM Uploaded 43 files and blobs.
09:38 PM Compilation starting.
09:38 PM Compilation: 17 files left.
09:38 PM Compilation: 11 files left.
09:38 PM Compilation completed.
09:38 PM Starting deployment.
09:38 PM Checking if deployment succeeded.
09:38 PM Deployment successful.
09:38 PM Checking if updated app version is serving.
09:38 PM Completed update of app: tomcampbell, version: 1

Running your newly deployed cloud app;

To start the app:

  • Open http://tomcampbell.appspot.com in the browser.

Troubleshooting: Do you need to update your version in GAE?

The first time you do this everything will happen as expected. But you may repeat this process later and discover your deployed app does not seem to have updated even if you changed the version number in app.yaml.

That's because GAE keeps several versions of your app available at any one time (currently it's 10 versions) and you need to choose which version you want as the "default".

The first time you upload it's easy, because that becomes the current version. App Engine serves pages from that version automatically.

If you leave the version number the same in app.yaml when you upload a new version of an app, App Engine silently overwrites the version you're uploading.

If you change the version number in app.yaml, however, you must then select that as the current version manually.

Here's how to see which version is current.

Checking which Google App Engine version is the current one (default)

To find out which version is current:

A list of versions appears. Here's what it looks like the first time you upload an app:

Google App Engine: The first version of an uploaded app

TODO: Improving this document

  • Explain Admin is disabled because insecure channel message and how to enable HTTPS

  • I got this message on localhost after running appcfg.py

The authentication flow has completed.
  • See if there's ever a reason to answer n to this question:
Allow dev_appserver to check for updates on startup? (Y/n):

TODO: This is probably outdated

$ appcfg.py update ../web2py

The first time you do this, you'll be asked for permission by GAE to use your Google account:

Screen shot of Google App Engine appcfg permissions page

  • Choose Allow.

Importing python-MySQL

GAE deployment requires the MySQL-python package. If you have problems deploying, you may need to install it.

  • Installing the MySQL-python requires pip. See Installing pip to determine if you have pip, and how to install it if you don't.

$ sudo -H pip install MySQL-python

Troubleshooting

ImportError: Cannot import module....modules.MySQLdb

At the time of writing there's a problem running this on recent versions of Macintosh OS X.

If you get output like this in the terminal, you need a patch. The meat of the message is ImportError: Cannot import module....modules.MySQLdb.

ERROR    2016-01-05 03:13:53,224 restricted.py:174] Traceback (most recent call last):
  File "/Users/tom/web2py/gluon/restricted.py", line 227, in restricted
    exec ccode in environment
  File "/Users/tom/web2py/applications/test/models/db.py", line 18, in <module>
    import MySQLdb as mysql
  File "/Users/tom/web2py/web2py/gluon/custom_import.py", line 89, in custom_importer
    raise ImportError, 'Cannot import module %s' % str(e)
ImportError: Cannot import module 'applications.test.modules.MySQLdb'

It's because of changes to OS X that restrct the use of relative path names in packages. See MySQL Improperly Configured Reason: unsafe use of relative path on stackoverflow.

  • The fix is to run the install_name_tool program:
$ sudo install_name_tool -change libmysqlclient.18.dylib \
  /usr/local/mysql/lib/libmysqlclient.18.dylib \
  /Library/Python/2.7/site-packages/_mysql.so

Resources

results matching ""

    No results matching ""