Domanda

When testing a Google App Engine app with the Launcher, the Launcher will start a local server, and open a tab listening to http://localhost:8080/ If the App.yaml file is configured to point to a html file, then the webpage will open. Like if your home page is index.html

app.yaml file

application: myProjectName
version: 2
runtime: python27
threadsafe: false
api_version: 1
handlers:
- url: .*
  static_dir: index.html

If the app.yaml is configured to point to a python script in the root url, I don't know how to get the script to load a web page:

app.yaml file

- url: /.*
  script: main.py

If my main.py Python script is:

import webbrowser
webbrowser.open_new("README.html")

That will open the README.html file in my browser when I run the code from the Python Shell, but if I launch the app from Google App Engine Launcher, it won't load the html file. How do I get the .py file to open an HTML file after the Launcher has started the app on the localhost:8000 ?

I'm looking at a Google example, and it uses a WSGIApplication webapp I guess. First the Python code goes through an authorization process, then at the end of the script, there is this code:

# Create an WSGI application suitable for running on App Engine
application = webapp.WSGIApplication(
    [('/', MainPage), ('/svc', ServiceHandler), ('/about', AboutHandler),
     ('/user', UserHandler)],
    # XXX Set to False in production.
    debug=True
)


def main():
  """Main entry point for executing a request with this handler."""
  run_wsgi_app(application)


if __name__ == "__main__":
    main()

I'd appreciate any feedback from anyone who has any experience with this.

È stato utile?

Soluzione

The simplest example that I know is the hello world in the documentation:

# helloworld.py
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)

The corresponding app.yaml is:

application: your-app-id
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /.*
  script: helloworld.application

You create a class MainPage -- whenever you make a request to localhost:8080/ (note the slash is unncessary), you will be directed to the main page. the application is responsible for routing the request to the proper class and creating a new instance of that class for each request. It also calls the get or post or whatever HTTP method. Whatever you write into the response is what gets returned to the browser as the web page.


Now a single page isn't all that interesting. Maybe you want localhost:8080/goodbye as well. Then you just add another class and "register" it with the application:

# helloworld.py
import webapp2

class MainPage(webapp2.RequestHandler):

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

class GoodbyePage(webapp2.RequestHandler):

    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('Goodbye, World.  Time to sleep.')

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

No changes to app.yaml are necessary at this point.


Life might be kind of frustrating if you needed to keep all your pages in a single file though. We can break this into 2 (or more) files by modifying app.yaml.

application: your-app-id
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /goodbye
  script: goodbye.app

- url: /.*
  script: helloworld.application

helloworld.py is the same as the first example. goodbye.py looks like this:

# goodbye.py
import webapp2

class GoodbyePage(webapp2.RequestHandler):

    def get(self):
        self.response.headers['Content-Type'] = 'text/html'
        self.response.write('<html><head></head><body>Goodbye!</body></html>')

app = webapp2.WSGIApplication([
    ('/goodbye', GoodbyePage),
], debug=True)

The urls in app.yaml are regular expressions -- you want to order them from most specific to least specific (otherwise, you might handle the request with the wrong handler). Also note that the convention in app.yaml is script: <module_name>.<variable_name> when we set it up this way.

Altri suggerimenti

Here is another example without Jinja2. To serve HTML with Python you simply need these 3 simple things.

1) Use the webapp2 Python module.

import webapp2

2) Read your HTML file into a variable:

INDEX_HTML = open('index.html').read()

3) Then write it out when a certain URL is sent:

self.response.out.write(INDEX_HTML)

This is the full Python script:

import cgi
import webapp2

class MainPage(webapp2.RequestHandler):
    def get(self):
        INDEX_HTML = open('index.html').read()
        self.response.out.write(INDEX_HTML)

class PageTwo(webapp2.RequestHandler):
    def post(self):
        self.response.write('<html><body>You wrote:<pre>')
        self.response.write(cgi.escape(self.request.get('content')))
        self.response.write('</pre></body></html>')

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

Note that your app.yaml configuration needs to be correct, and you need an HTML file. The webapp2 module provides a RequestHandler that can route your URL requests. (Display different webpage content) Here is a GitHub repository with the code, manifest app.yaml file and the index.html file.

Serve HTML with Python

This gets the HTML from a file, then writes it to the browser. This is actually more of what I was looking for:

class MainPage(webapp2.RequestHandler):
    def get(self):
        template = JINJA_ENVIRONMENT.get_template('index.html')
        self.response.write(template.render())

This is the entire module:

import cgi
import os

import jinja2
import webapp2

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    extensions=['jinja2.ext.autoescape'],
    autoescape=True)

class MainPage(webapp2.RequestHandler):
    def get(self):
        template = JINJA_ENVIRONMENT.get_template('index.html')
        self.response.write(template.render())

class PageTwo(webapp2.RequestHandler):
    def post(self):
        self.response.write('<html><body>You wrote:<pre>')
        self.response.write(cgi.escape(self.request.get('content')))
        self.response.write('</pre></body></html>')

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

Here is a link to the Git Hub repository: Get Template HTML, and write to browser

I saw an interesting variation of the app.yaml configuration file in a code example:

- url: /
  static_files: index.html
  upload: index.html

Even though the webbapp2 Request Handler is serving a particular HTML file based on the URL, the app.yaml file also controls what happens when different URL's are sent. The app.yaml file can be configured to run the python script AND upload a particular HTML file. If your application has lots of sub-directories, and the main.py script doesn't load until the end of your app.yaml file, configuring the app.yaml file to load static HTML right up front may cause your main page to load faster:

application: YourProjectNameHere
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:
#Even though the main.py script also loads the index,
#this is faster if lots of processing
- url: /
  static_files: index.html
  upload: index.html

- url: /Client_Style
  static_dir: Client_Style

- url: /Client_Pages
  static_dir: Client_Pages

- url: /Client_Script
  static_dir: Client_Script

- url: /Library
  static_dir: Library

- url: /apiclient
  static_dir: apiclient

- url: /Client_Data
  static_dir: Client_Data

- url: /oauth2client
  static_dir: oauth2client

- url: /uritemplate
  static_dir: uritemplate

- url: /.*
  script: main.application

libraries:
- name: webapp2
  version: latest
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top