I am trying to break my app into separate scripts. Part of this effort meant breaking the api calls into it's own file. However the calls to the api (like http://example.com/api/game/new no longer work).
My app.yaml contains this:
- url: /api.*
script: api.py
which seems to be redirecting properly because this configuration works:
def main():
application = webapp.WSGIApplication([('/.*', TestPage)], debug=True)
util.run_wsgi_app(application)
however this one doesn't:
def main():
application = webapp.WSGIApplication([('/game/new$', CreateGame),
('/game/(d+)$', GameHandler)],
debug=True)
util.run_wsgi_app(application)
The URL patterns you use in the WSGI application have to be the full path - eg, /api/game/.... The App Engine infrastructure uses the regular expressions in app.yaml to route requests, but it does not modify the request path based on them.
My guess is you are trying to pass some arguments to your handler.
Try this. It will give you a hint.
#!/usr/bin/env python
import wsgiref.handlers
from google.appengine.ext import webapp
class MyHandler(webapp.RequestHandler):
def get(self, string=None):
if string:
self.response.out.write("Hello World!! %s" % string)
else:
self.response.out.write("Hello World!! (and no word)")
def main():
app = webapp.WSGIApplication([
(r'/word/(\w+)/?$', MyHandler),
(r'.*', MyHandler),
], debug=True)
wsgiref.handlers.CGIHandler().run(app)
if __name__ == "__main__":
main()
Hope it helps. Cheers.
Related
I am using Flask to build a tool to view data locally in a browser. I want to pass the directory containing the data as a command line argument, and then pass it to the appropriate routing function to do the rendering.
This does what I want, but with global variables:
dataDir = None
def initializeData(pathname):
global dataDir
dataDir = pathname
#app.route('/')
def home():
# Use dataDir as desired
if __name__ == '__main__':
initializeData(sys.argv[1])
app = Flask(__name__)
app.run()
Is there a better way to communicate between the command line and my routes?
Your flask app has a config property. Also, this code will fail with a NameError. You want something like this:
import sys
from flask import Flask
app = Flask(__name__)
#app.route('/')
def home():
return 'You wanted {!r} directory'.format(app.config.get('some_setting'))
if __name__ == '__main__':
app.config['some_setting'] = sys.argv[1]
app.run()
Consider using app.config.from_json('config.json') so that you can configure your env parameters in a json file.
I'm trying to get a web.py application running on GAE. I hoped that sth like the following might work
import web
from google.appengine.ext.webapp.util import run_wsgi_app
[...]
def main():
app = web.application(urls, globals())
run_wsgi_app(app)
But obviously the app object doesn't conform with the run_wsgi_app function's expectations. The error msg says sth like app has no __call__ function, so I tried passing app.run instead, but that didn't work either.
How can I make the call to run_wsgi_app work?
Here is a snippet of StackPrinter, a webpy application that runs on top of Google App Engine.
from google.appengine.ext.webapp.util import run_wsgi_app
import web
...
app = web.application(urls, globals())
def main():
application = app.wsgifunc()
run_wsgi_app(application)
if __name__ == '__main__':
main()
You don't need to import or use run_wsgi_app, web.py has a runcgi method that works perfectly!
if __name__ == '__main__':
app.cgirun()
Scenario 1
This involves using one "gateway" route in app.yaml and then choosing the RequestHandler in the WSGIApplication.
app.yaml
- url: /.*
script: main.py
main.py
from google.appengine.ext import webapp
class Page1(webapp.RequestHandler):
def get(self):
self.response.out.write("Page 1")
class Page2(webapp.RequestHandler):
def get(self):
self.response.out.write("Page 2")
application = webapp.WSGIApplication([
('/page1/', Page1),
('/page2/', Page2),
], debug=True)
def main():
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
Scenario 2:
This involves defining two routes in app.yaml and then two separate scripts for each (page1.py and page2.py).
app.yaml
- url: /page1/
script: page1.py
- url: /page2/
script: page2.py
page1.py
from google.appengine.ext import webapp
class Page1(webapp.RequestHandler):
def get(self):
self.response.out.write("Page 1")
application = webapp.WSGIApplication([
('/page1/', Page1),
], debug=True)
def main():
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
page2.py
from google.appengine.ext import webapp
class Page2(webapp.RequestHandler):
def get(self):
self.response.out.write("Page 2")
application = webapp.WSGIApplication([
('/page2/', Page2),
], debug=True)
def main():
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
Question
What are the benefits and drawbacks of each pattern? Is one much faster than the other?
The only performance implication relates to the loading of modules: Modules are loaded on an instance when they're first used, and splitting things up requires fewer module loads to serve a page on a new instance.
This is pretty minimal, though, as you can just as easily have the handler script dynamically load the needed module on-demand - and that's what many common frameworks already do.
In general, app.yaml routing is designed for routing between distinct components or applications. For example, remote_api and deferred both have their own handlers. It's perfectly reasonable, therefore, to have a single handler defined for your app that handles everything else.
I don't believe there's any performance implication, but splitting your app into files based on functionality will help you manage it better, especially if it's being developed by multiple people.
For example, all handlers that have to do with viewing, editing, deleting, etc., pages could be in pages.py while all handlers that have to do with viewing, etc., user profiles could be in user_profiles.py, and all handlers having to do with a JSON REST API could be in rest_api.py, and so on.
But again, I don't believe this has any runtime performance implication, just a development-time performance implication.
I want to send a string to a python function I have written and want to display the return value of that function on a web page. After some initial research, WSGI sounds like the way to go. Preferably, I don't want to use any fancy frameworks. I'm pretty sure some one has done this before. Need some reassurance. Thanks!
You can try Flask, it's a framework, but tiny and 100% WSGI 1.0 compliant.
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
Note: Flask sits on top of Werkzeug and may need other libraries like sqlalchemy for DB work or jinja2 for templating.
You can use cgi...
#!/usr/bin/env python
import cgi
def myMethod(some_parameter):
// do stuff
return something
form = cgi.FieldStorage()
my_passed_in_param = form.getvalue("var_passed_in")
my_output = myMethod(my_passed_in_param)
print "Content-Type: text/html\n"
print my_output
This is just a very simple example. Also, your content-type may be json or plain text... just wanted to show an example.
In addition to Flask, bottle is also simple and WSGI compliant:
from bottle import route, run
#route('/hello/:name')
def hello(name):
return 'Hello, %s' % name
run(host='localhost', port=8080)
# --> http://localhost:8080/hello/world
I'm just starting learning google app engine.
When I enter the following code below, all I got is "Hello world!"
I think the desired result is "Hello, webapp World!"
What am I missing? I even try copying the google framework folder to live in the same folder as my app.
Thanks.
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class MainPage(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Hello, webapp World!')
application = webapp.WSGIApplication(
[('/', MainPage)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
Running exactly this code DOES give me the desired output. I suspect you must be erroneously running some other code, since there's absolutely no way this code as given could possibly emit what you observe.