Yaml file addressing in GAE using Python - python

Here is the file structure :
--src
-----\app.yaml
-----\bl
-----\bl\calc.html
-----\calc.py
-----\Main.py
I want to get to this address "localhost/bl/calc.html" and here is my yaml file:
- url: /bl
static_dir: bl
- url: /bl/.*
script: calc.py
- url: /.*
script: Main.py
In the Main.py I have this :
from calc import Calc
application = webapp.WSGIApplication([
('/', MainPage),
('/bl/calc', Calc)
], debug=True)
But I got just "This webpage is not found" for both http://localhost/bl/calc and http://localhost/bl/calc.html
I got really confused With this YAML file and GAE
I Dont know how to fix it. Should I have same application config in Calc file ?

Directives in app.yaml are evaluated in order, top to bottom. Because you have a static_dir directive for /bl/ before the script handlers for /bl/ and .*, any requests for that path will be satisfied by the static directory, not the script. Decide which you want - static or script - and add only that to app.yaml.

The yaml file tells what file to run for a given path. Since you're setting up a WSGIApplication in Main.py that will handle requests to /bl/calc with your Calc object, you don't need the lines in your app.yaml file specifying calc.py. Remove those lines and your program should work.

Related

Flask Logging in ElasticBeanstalk

I am trying to set up Logging for my Flask app which is deployed in ElasticBeanstalk.
I have a basic logging in place that prints stuff in my console.
But on deploying in Beanstalk, I am not able to see any of the application logs.
Is there any specific config that needs to be setup in order to achieve this?
Just sharing a sample code.
user.py
import logging
class User(Resource):
def details(self):
user_info = "Hello"
logging.info(user_info)
You can add a config file to your .ebextensions folder that adds your application's logs to the logs that EB downloads automatically.
Assuming that your application logs to a folder called logs in the Flask app root, you would make a file called .ebextensions/logging.config that looks like this:
files:
"/opt/elasticbeanstalk/tasks/taillogs.d/your_app_name_logs.conf" :
mode: "000644"
owner: root
group: root
content: |
/var/app/current/logs/*.log
(Which is a slight variation on the official documents here: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.logging.html)
Then, after you deploy, you should be able to use the GUI to pull down logs.

Python & GAE - StringType write() argument type parsing

When running dev_appserver.py ., I get the following error when trying to access http://localhost:8080:
Traceback (most recent call last):
File "/usr/local/Cellar/python#2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 86, in run
self.finish_response()
File "/usr/local/Cellar/python#2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 128, in finish_response
self.write(data)
File "/usr/local/Cellar/python#2/2.7.15_1/Frameworks/Python.framework/Versions 2.7/lib/python2.7/wsgiref/handlers.py", line 204, in write
assert type(data) is StringType,"write() argument must be string"
AssertionError: write() argument must be string
I've searched and it seems to come back to my app.yaml file, per these links:
SO Question for GAE Assertion Error
Russian Question site with
same information
I'm just not sure how to go about debugging it. Below is my app.yaml file and my main.py file. I'm super new to the GAE platform and any help would be appreciated.
app.yaml file:
application: gqtimer
version: 1-56
runtime: python27
api_version: 1
threadsafe: false
handlers:
- url: /favicon.ico
static_files: static/images/favicon.ico
upload: static/images/favicon.ico
- url: /_ah/login_required
script: main.py
- url: /static
static_dir: static
- url: /player.*
script: main.py
login: required
- url: /stat.*
script: main.py
login: required
- url: .*
script: main.py
libraries:
- name: django
version: "1.11"
main.py file:
#!/usr/bin/env python
#
import config
import os
import sys
# Force sys.path to have our own directory first, so we can import from it.
sys.path.insert(0, config.APP_ROOT_DIR)
sys.path.insert(1, os.path.join(config.APP_ROOT_DIR, 'externals'))
os.environ["DJANGO_SETTINGS_MODULE"] = "settings"
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.dist import use_library
use_library('django', '1.2')
from handlers import error, timer, do_openid_login
def main():
application = webapp.WSGIApplication([('/', timer.ExportHandler),
('/_ah/login_required', do_openid_login.OpenIdLoginHandler),
('/player/([-\w]+)', timer.PlayerHandler),
('/player/([-\w]+)/archives', timer.ArchivesHandler),
('/stat/([-\w]+)', timer.StatHandler),
('/stat/([-\w]+)/delete', timer.StatDeleteHandler),
# If we make it this far then the page we are looking
# for does not exist
('/.*', error.Error404Handler),
],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
Indeed, your app.yaml file might not be properly mapping your application code. You need to:
take the application variable outside of the main() function so that it becomes a global variable in the main.py module (and maybe rename it to app as well - just to stay inline with the official convention and documentation examples)
replace the script: main.py statements from your app.yaml's handlers with main.application (or main.app if renamed as mentioned above) - this is the reference to the above-mentioned global variable. From the script row in the Handlers element table:
A script: directive must be a python import path, for example,
package.module.app that points to a WSGI application. The last component of a script: directive using a Python module path is
the name of a global variable in the module: that variable must be a
WSGI app, and is usually called app by convention.
I'd also recommend explicitly passing the app.yaml as argument to dev_appserver.py instead of the app's directory (. in your case) - occasionally the auto-detection doesn't behave as expected. It's also the only way to run multiple services and/or using a dispatch.yaml file for routing, so it's a good habit.

Writing doctests for pyramid web app which depend on settings in ini file

I would like to write doctests for my pyramid web app, using the webtest module. I tried it like this:
from my_webapp import main
from webtest import TestApp
app = TestApp(main({}))
result = app.get('/')
This raises a KeyError (because some.url is not known) when my code reaches this line:
url = request.registry.settings['some.url']
The value of some.url is specified in the paster ini file of my application. Is there a simple way to use my development.ini when running my test code? I did not yet fully understand how/when the ini file is loaded during pyramid start up, so it's hard to figure out where to load it while testing.
main is invoked with the contents of your ini file. A simple way to load your app from an ini is:
from pyramid.paster import get_app
app = get_app('testing.ini#main')
test_app = TestApp(app)
This expects "testing.ini" to be in the current working directory, so you may need to tweak that. If you'd like it to be relative to a spot in your tree you can use:
import os.path
import some_module
here = os.path.dirname(some_module.__file__)
app = get_app(os.path.join(here, 'testing.ini'))

mapping values are not allowed here ... in foo.py

I have this GAE python code
In file foo.py
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Hello Foo')
app = webapp2.WSGIApplication([('/', MainPage)], debug = True)
in file app.yaml
application: foo
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: foo.app
I get this error pointing to the third line in file foo.py ( class MainPage(webapp2.RequestHandler): )
Obs. Begin reading from the end of the message
...
line 172, in _HandleEvents
for event in events:
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/yaml_listener.py", line 212, in _GenerateEventParameters
raise yaml_errors.EventListenerYAMLError(e)
google.appengine.api.yaml_errors.EventListenerYAMLError: mapping values are not allowed here
in "foo.py", line 3, column 39
I would appreciate a good help
thanks
Sam
This kind of error occurs if you start the application the wrong way: dev_appserver.py foo.py. You need a directory, e.g., foo with foo/foo.py and foo/app.yaml and then start the program from the parent directory with dev_appserver.py foo/ or in the directory itself with dev_appserver.py .
There is nothing wrong with your code. I copy and pasted both into files and ran them on my Win7 system using App Engine SDK release: "1.7.7" and it served up the page without errors.
You may have issues with the files or your setup.
Have you tried the File->Creating New Application menu option? It will create a new application called engineapp that will display "Hello world!" when browsed on the localhost machine.

Appstats are only working for one WSGIApplication

I've split handlers between 2 python files (main.py and main_cms.py). app.yaml defines the URLs that each python file will handle.
When I look at the Appstats, only the handlers from one of the 2 python files are profiled (the ones from main.py).
The 'magic' of webapp_add_wsgi_middleware(app) always used to work just fine, until the split. How can I make Appstats recording apply to all handlers?
appengine_config.py:
def webapp_add_wsgi_middleware(app):
from google.appengine.ext.appstats import recording
app = recording.appstats_wsgi_middleware(app)
return app
app.yaml:
builtins:
- appstats: on
...
- url: /services/.*
script: main.application
- url: /cms.*
script: main_cms.application
main.py and main_cms.py:
application = webapp2.WSGIApplication(url_mapping, config=config)
Running python2.7 / GAE 1.6.3, the dev_appserver.py shows Appstats correct for all handlers. The described problem is only seen in production.

Categories