It started out so simple. I found this little module, RandomWords, for generating random words or word lists and I wanted to show how to add this package to the Standard GAE environment (GAE). So I modified the GAE HelloWorld app to say "Hello <random_word>".  This did not work. GAE only allows you to import modules that are written in pure Python and RandomWords compiles a C-shared object as part of its install. Now curious, I found a module, names, written in pure Python that generates random first names, last name, or full names based on the 1990 US Census data (http://www.census.gov/main/www/cen1990.html). This blog post covers what I did to make this work.

The question came up: How do you use RandomWords? Answer: Move it to Google Managed VMs (MVM). At least for Python, there are two ways to port my HelloCensus app to Managed VMs. The first is to use a custom install with a base compatible with the Standard GAE environment. This is the subject of Part II: Porting Python App to a compatible MVM environment. Obviously, the third part of this is porting of my Standard GAE environment to the standard MVM environment.

Adding a Python Module in the Standard GAE Development Environment

 
Step 1:  Creating a Google Project

This is just standard stuff on console.cloud.google.com. I did it so that I could measure the cost of this exercise. The project name is roi-add-gae.

Step 2: Creating the Virtual Environment

Create a virtual environment.

  • Execute: virtualenv HelloNames
  • Execute: cd HelloNames
  • Execute: bin/activate
Step 3:  Creating the helloNames.py and the index.html Files

Figure 1:  helloNames.py

  1 import os
  2
  3 import jinja2
  4 import webapp2
  5
  6 import names
  7
  8 JINJA_ENVIRONMENT = jinja2.Environment(
  9     loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
 10     extensions=['jinja2.ext.autoescape'],
 11     autoescape=True)
 12
 13 class MainPage(webapp2.RequestHandler):
 14     def get(self):
 15         random_name = names.get_full_name()
 16
 17         template_values = {
 18             'random_name': random_name,
 19         }
 20
 21         template = JINJA_ENVIRONMENT.get_template('index.html')
 22         self.response.write(template.render(template_values))
 23
 24 app = webapp2.WSGIApplication([
 25     ('/', MainPage),
 26 ], debug=True)

 

Figure 2: index.html

  1 <!DOCTYPE html>
  2 {% autoescape true %}
  3 <html>
  4   <head>
  5   </head>
  6   <body>
  7     <p> Hello {{ random_name }} </p>
  8   </body>
  9 </html>
 10 {% endautoescape %}
 

Nothing very exciting as far as coding goes.

Three of the imports are of interest—webapp2 is a defaulted module in GAE. If you can live with the default version which shows up as deprecated in the documentation, there is nothing to do. I want to use a newer version—jinja2 has to be specified in the Libraries passage of app.yaml to be included in the environment. To see all of the provided modules, see https://cloud.google.com/appengine/docs/python/tools/libraries27#runtime-libraries

Figure 3: app.yaml

  1 runtime: python27
  2 api_version: 1
  3 threadsafe: true
  4
  5 handlers:
  6 - url: /.*
  7   script: helloNames.app
  8
  9 libraries:
 10 - name: webapp2
 11   version: "2.5.1"
 12 - name: jinja2
 13   version: "2.6"

 

Lines 10 through 13 tell the GAE to include these libraries. Line 10 and 11 include webapp2 version 2.5.1 which is later than the default version and that is the reason it is here. Lines 12 and 13 add jinja2 at version 2.6.  If the version line is not included, at the time of deployment, the latest version of the module is added. The version of the module can only be changed by redeploying the app.

Making the module names available is a three-step process.

  1. In the root directory of the app, the directory with app.yaml, create a new file call appengine_config.py. Figure 4, appengine_config.py, shows the two lines which must be in the file.

Figure 4: appengine_config.py

from google.appengine.ext import vendor
vendor.add('lib')

 

lib is the name of a directory in the root of the app which will contain the modules to be imported by the app.

  1. Change to the root directory of the app and make the directory lib with the command mkdir lib.
  1. Still in the root directory, use pip to install the module in lib.

$ pip install –t lib names

Step 4:  Testing in the Development Environment
  1. Execute: dev.appserver.py   
  2. Open a browser window to localhost:8080

Porting1

3.Kill the dev server with a <Ctrl-C>

Step 5: Uploading to Production and Testing
  1. Execute: gcloud config set project roi-add-gae
  2. Execute: gcloud preview app deploy
  3. Open a browser to https://roi-add-gae.appspot.com

Porting2

Step 6:  Cleanup

Execute: deactivate

This stops the virtual environment. What to do about the code and control files? I will zip up the directory and archive in the Python folder on the Google Drive.

Leave a Reply

Your email address will not be published.