What is web.session.Session in the python web.py module - python

I'm currently learning Python and can't work out what the web.session.Session is in the follow game program:
app = web.application(urls, globals())
session = web.session.Session(app, web.session.DiskStore('sessions'), initializer={'room': None})
What are app, Diskstore, and initializer?

This web.session module gives you the session support,
initializer - You can set the initial session which is not mandatory.
eg: initializer={'room': None} sets the initial session of room to None.
DiskStore makes the session to save in disk whereas DBStore stores session in databases.
app gives the application instance created as
web.application(urls, globals()) with URLs which mapped to the relevant classes.
Refer this.

Related

Why is id of object returned by session._get_current_object() is changed on every request, while id of session remains unchanged?

I am using:
Python 3.6.1
Flask 0.12.2
Section on session of Flask documentation says that:
This is a proxy.
and section on proxies elaborates that:
Some of the objects provided by Flask are proxies to other objects.
The reason behind this is that these proxies are shared between
threads and they have to dispatch to the actual object bound to a
thread behind the scenes as necessary. ...
If you need to get access
to the underlying object that is proxied, you can use the
_get_current_object() method
This all is pretty much straightforward.
But when I try the following:
from flask import (
Flask,
session,
)
app = Flask(__name__)
app.secret_key = 'some random secret key'
#app.route('/')
def index():
print("session ID is: {}".format(id(session)))
print("session._get_current_object() ID is: {}".format(id(session._get_current_object())))
print('________________________________')
return 'Check the console! ;-)'
each time I make a request to / — the value of id(session._get_current_object()) is different, while id(session) remains the same.
Following Flask documentation, quoted above, it should be the other way around. So why is this happening?
UPDATE
inspired by brunns's suggestion in the comments to his answer, that there is one underlying object per thread
Here is some code, to test assumption that there is one underlying session object (session._get_current_object()) per thread:
import threading
from flask import (
Flask,
session,
)
app = Flask(__name__)
app.secret_key = 'some random secret key'
#app.route('/')
def index():
print("session ID is: {}".format(id(session)))
print("session._get_current_object() ID is: {}".format(id(session._get_current_object())))
print("threading.current_thread().ident is: {}".format(threading.current_thread().ident))
print('________________________________')
return 'Check the console! ;-)'
Despite the expectations, threading.current_thread().ident) is never changed, while is id(session._get_current_object() is changing.
session is an object you have imported from the flask module. You only import it once, and it doesn't change, so nor will its id(). It's shared between threads, and it's a proxy to the underlying objects.
Each request may be run on a different thread, and each will have a different underlying object, so they may have different id()s.

aiohttp: get current running app

Currently I'm doing the following to get the current running app
async def handler(request):
app = request.app
Isn't there another way for getting the current running app? Consider the below snippet (the default for author_id):
class Comment(DeclarativeBase):
author_id = Column(Integer, ForeignKey('member.id'), default=Member.current_logged_in())
class Member(DeclarativeBase):
#classmethod
def current_logged_in()
pass
As the session is kept in the current running app and as you can see it is only accessible from the incoming request, how can I get the current running app to use the session for determining the current_logged_in user and thus be used as the default value for Comment's author_id?
I wish I have made my point.
Right now there is no implicit context for aiohttp application.
BTW don't do synchronous calls (SQLAlchemy ORM in your case) from aiohttp code.

Why is an instance of webapp.WSGIApplication always defined as a global variable in google app engine code?

I'm starting to learn to use google app engine and, in much of the code I've come across, they declare the instance of the webapp.WSGIApplication as a global variable. This doesn't seem to be necessary, as the code works fine when it is locally declared in the main function.
I was always advised that global variables should be avoided. So is there a good, or even not so good, reason that it's done this way?
Example:
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
application = webapp.WSGIApplication([ ('/', MainPage), ('/sign', Guestbook)], debug=True)
def main():
wsgiref.handlers.CGIHandler().run(application)
Why not do the following, which also works:
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
def main():
application = webapp.WSGIApplication([ ('/', MainPage), ('/sign', Guestbook)], debug=True)
wsgiref.handlers.CGIHandler().run(application)
This also works in examples with multiple request handlers.
Google App Engine offers a neat feature called App caching.
The first time the main handler is invoked, the full script is evaluated importing the modules and creating the global elements.
If the handler is called after the script has already been evaluated, the app instance simply calls its main() function directly.
The overhead of creating the global elements is payed just the first time and the objects created can be reused by multiple requests saving time and resources.
That said, it is highly recommended to pick the first choice, declaring the application variable outside the main() function.
It's possibly related to the application caching, rather than recreating it each time (for performance):
You can tell App Engine to cache the handler script itself, in addition to imported modules. If the handler script defines a function named main(), then the script and its global environment will be cached like an imported module. The first request for the script on a given web server evaluates the script normally. For subsequent requests, App Engine calls the main() function in the cached environment.
Taken from here:
http://code.google.com/appengine/docs/python/runtime.html#App_Caching

Werkzeug and SQLAlchemy 0.5x session

Updated:
Going through the Werkzeug link text tutorial, got stack with creating SQLAlchemy session using sessionmaker() instead of create_session() as recommended.
Note: it is not about SA, it is about Werkzeug.
Werkzeug tutorial:
session = scoped_session(lambda: create_session(bind=application.database_engine,
autoflush=True, autocommit=False), local_manager.get_ident)
I asked how to achieve the same using sessionmaker():
As a result guys from #pocoo RCI helped me with this:
session = scoped_session(lambda: sessionmaker(bind=application.database_engine)(),
local_manager.get_ident)
without () at the end of sessionmaker(**args) it kept giving me an error:
RuntimeError: no object bound to application
P.S. if delete lambda it will not work.
sessionmaker() returns a session factory, not a session itself. scoped_session() takes a session factory as argument. So just omit the lambda: and pass the result of sessionmaker() directly to scoped_session().

Can't get Beaker sessions to work (KeyError)

I'm a newb to the Python world and am having the dangest time with getting sessions to work in my web frameworks. I've tried getting Beaker sessions to work with the webpy framework and the Juno framework. And in both frameworks I always get a KeyError when I try to start the session.
Here is the error message in webpy (its pretty much the exact same thing when I try to use beaker sessions in Juno too)...
ERROR
<type 'exceptions.KeyError'> at /
'beaker.session'
Python /Users/tyler/Dropbox/Code/sites/webpy1/code.py in GET, line 15
Web GET http://localhost:1234/
15. session = web.ctx.environ['beaker.session']
CODE
import web
import beaker.session
from beaker.middleware import SessionMiddleware
urls = (
'/', 'index'
)
class index:
def GET(self):
session = web.ctx.environ['beaker.session']
return "hello"
app = web.application(urls, globals())
if __name__ == "__main__": app.run()
You haven't created the session object yet, so you can't find it in the environment (the KeyError simply means "beaker.session is not in this dictionary").
Note that I don't know either webpy nor beaker very well, so I can't give you deeper advice, but from what I understand from the docs and source this should get you started:
if __name__ == "__main__": app.run(SessionMiddleware)

Categories