I have implemented a code to calculate api time.
#api.app.before_request
def before_request():
g.request_start_time = time.time()
#api.app.after_request
def after_request():
elapsed = time.time() - g.request_start_time ------> Error here.
I am having error for ~1-2% api calls.
Error:
'_AppCtxGlobals' object has no attribute 'request_start_time'
I am not able to debug this. This can only happen if :
the api does not pass through before_request function.
the global context get reset in between the code.
First seems not to be happen as every api request should pass the before_request function.
I am not able to find when the second case can occur. What are the scenarios when the global context get reset in between call.
Is there anything I am missing here ?
EDIT:
I have been observing the cases when this error is occurring and found the similarity that all calls were having 400 BAD REQUEST. But I am still not able to get the root cause of this.
I had a similar issue and is due because you called a variable g, so flask confuse it with the global application context also called g.
Have a look here:
https://flask.palletsprojects.com/en/1.1.x/api/#flask.ctx._AppCtxGlobals
Creating an app context automatically creates this object, which is made available as the g proxy.
So try renaming your g variable in g.request_start_time = time.time()that you probably inherit from somewhere else.
If you are referring the flask context and having error correlated to 404 requests, it might be that when you call after_request() it does not find any attribute g.request_start_time , maybe because if requests fail the attribute is not created.
Related
According to the Django channel docs,
You get access to a user’s normal Django session using the http_session
decorator - that gives you a message.http_session attribute that behaves
just like request.session. You can go one further and use
http_session_user which will provide a message.user attribute as well as
the session attribute.
Is there anyway I can set a session variable like so?
I did try it, and I get an error saying NoneType is not iterable.
if 'username' not in message.http_session:
message.http_session['username'] = 'temp'
In other words, message.http_session returns a NoneType. I've tried using the decorators #http_session and #channel_session_user_from_http, but they didn't help either.
You just set the variable.
foo = 'bar'
And it persists throughout the session
So I'm pretty new to Flask and I'm trying to make my mind around one thing. So, if I understand well when you write a function within a Flask app and you use the #app.route decorator in that function, it only runs when you hit that path/url.
I have a small oauth app written in Flask that goes through all the authorization flow and then it return the token.
My question is how do I get that token from the #decorated function? For example, lets say I have something like this:
#app.route(/token/)
def getToken(code): #code from the callback url.
#/Stuff to get the Token/
#/**********************/
return token
If I hit the (/token/) url-path the function returns the token. But now I need to get that token and use it in another function to write and read from the API I just got the token from. My initial thought was doing this:
token = getToken(code)
But if I do that, I get this error:
RuntimeError: working outside of request context
So again, my question is, how do I get the token so I can pass it as a parameter to other functions.
Extract the token generation code into a separate function, so that you can call it from anywhere, including the view function. It's a good practice to keep the application logic away from the view, and it also helps with unit testing.
I assume your route includes a placeholder for code, which you skipped:
def generateToken(code):
#/Stuff to get the Token/
#/**********************/
return token
#app.route('/token/<string:code>')
def getToken(code):
return generateToken(code)
Just keep in mind that generateToken shouldn't depend on the request object. If you need any request data (e.g. HTTP header), you should pass it explicitly in arguments. Otherwise you will get the "working outside of request context" exception you mentioned.
It is possible to call request-dependent views directly, but you need to mock the request object, which is a bit tricky. Read the request context documentation to learn more.
not sure what the context is. You could just call the method.
from yourmodule import get_token
def yourmethod():
token = get_token()
Otherwise, you could use the requests library in order to retrieve the data from the route
>>> import requests
>>> response = requests.get('www.yoursite.com/yourroute/')
>>> print response.text
If you're looking for unittests, Flask comes with a mock client
def test_get_token():
resp = self.app.get('/yourroute')
# do something with resp.data
I am using FLask-OAuthlib and want to do some caching/memoization using Flask-Cache. I've got caching setup on my views but I'm having trouble with caching this function:
#oauth.clientgetter
#cache.memoize(timeout=86400)
def load_client(client_id):
return DBSession.query(Client).filter_by(client_id=client_id).first()
The first time the function is run (not cached yet) it runs fine but when it gets it from cache something gets messed up somehow and says it's an invalid client. I don't know if it's caching it incorrectly or if having the #oauth.clientgetter decorator somehow screws up the caching. Everything works fine without caching and the client is valid. I've tried to move the function around like so, but get the same result:
class Client(Base):
__tablename__ = 'client'
__table_args__ = {'autoload': True}
user = relationship('User')
#classmethod
#cache.memoize(timeout=86400)
def get_client(cls,client_id):
return DBSession.query(cls).filter_by(client_id=client_id).first()
Then, in my view I have:
#oauth.clientgetter
def load_client(client_id):
return Client.get_client(client_id)
But this gives the same result. I am using redis as my cache backend and the keys/values I have are:
1) "flask_cache_Pwd2uVDVikMYMDNB+gVWlW"
2) "flask_cache_api.models.Client.get_client_memver"
3) "flask_cache_http://lvho.st:5000/me"
GET flask_cache_Pwd2uVDVikMYMDNB+gVWlW:
"!ccopy_reg\n_reconstructor\np1\n(capi.models\nClient\np2\nc__builtin__\nobject\np3\nNtRp4\n(dp5\nS'_sa_instance_state'\np6\ng1\n(csqlalchemy.orm.state\nInstanceState\np7\ng3\nNtRp8\n(dp9\nS'manager'\np10\ng1\n(csqlalchemy.orm.instrumentation\n_SerializeManager\np11\ng3\nNtRp12\n(dp13\nS'class_'\np14\ng2\nsbsS'class_'\np15\ng2\nsS'modified'\np16\nI00\nsS'committed_state'\np17\n(dp18\nsS'instance'\np19\ng4\nsS'callables'\np20\n(dp21\nsS'key'\np22\n(g2\n(S'Iu6copdawXIQIskY5kwPgxFgU7JoE9lTSqmlqw29'\np23\nttp24\nsS'expired'\np25\nI00\nsbsVuser_id\np26\nL4L\nsVname\np27\nS'Default'\np28\nsV_default_scopes\np29\nS'email'\np30\nsVclient_id\np31\ng23\nsV_redirect_uris\np32\nS'http://localhost:8000/authorized/'\np33\nsVactive\np34\nI1\nsVclient_secret\np35\nS'Vnw0YJjgNzR06KiwXWmYz7aSPu1ht7JnY1eRil4s5vXLM9N2ph'\np36\nsVdescription\np37\nNsb."
GET flask_cache_api.models.Client.get_client_memver:
"!S'+gVWlW'\np1\n."
Try reversing the order of your decorators:
#cache.memoize(timeout=86400)
#oauth.clientgetter
def load_client(client_id):
return DBSession.query(Client).filter_by(client_id=client_id).first()
EDIT
The problem seem to be that a Client object is not pickle-able, while cache.memoize relies on objects' pickle-ability. Therefor, in one case, you end up with an invalid-client error (the client object did not "survive" the picke-dump-then-pickle-load process), and in another case, with some kind of caching error which (silently) prevents the object from being cached (I'm not sure what mechanism causes this silent-handling).
In any case, it seems to me you shouldn't attempt to memoize your client object in the first place.
I am total newbie with cherrypy.
My setup: Arch Linux, Python 3.3, tornado, cherrypy 3.2
Trying to implement session handling for a web app using cherrypy.lib.sessions (for some reason often referred to as cherrypy.sessions in various forums, might be another version)
I am looking for an example of the following:
instantiate a session object
set a value of an arbitrarily named attribute
write session into a session file
read session info from session file
access the the value of the modified attribute
My (relevant) code:
import cherrypy
class RequestHandlerSubmittedRequest(tornado.web.RequestHandler):
def get(self):
SetState(self)
def SetState(self):
cherrypy.config.update({'tools.sessions.on': True})
cherrypy.config.update({'tools.sessions.storage_type': 'file'})
#directory does exist
cherrypy.config.update({'tools.sessions.storage_path': '/tmp/cherrypy_sessions'})
cherrypy.config.update({'tools.sessions.timeout': 60})
cherrypy.config.update({'tools.sessions.name': 'hhh'})
So far so good. Now:
obj_session = cherrypy.lib.sessions.FileSession
Here I get the first snag (or misunderstanding).
The returned obj_session contains no session ID of any kind, just an empty object frame. Also: no file is created at this point in /tmp/cherrypy_sessions -
should not it be there now? I would expect it to be created and named after its session ID.
OK, no ID in the object, let's assign one:
session_id = obj_session.generate_id(self)
This returns a long random string as it should I guess
And now I don't know how to proceed with assignments and saving calling obj_session.save() or obj_session.load() with several variations of input gives "AttributeError: 'module' object has no attribute X" where X can be "load" and couple of other keywords. Passing self or obj_session itself to the methods does not help, just changes the wording of the error. I must be going in a very wrong direction in general.
So, is there an example of those five steps above? I could not find one anywhere.
Thanks.
Igor
I noticed a strange behaviour today: It seems that, in the following example, the config.CLIENT variable stays persistent accross requests – even if the view gets passed an entirely different client_key, the query that gets the client is only executed once (per many requests), and then the config.CLIENT variable stays assigned.
It does not seem to be a database caching issue.
It happens with mod_python as well as with the test server (the variable is reassigned when the test server is restarted).
What am I missing here?
#views.py
from my_app import config
def get_client(client_key=None):
if config.CLIENT == None:
config.CLIENT = get_object_or_404(Client, key__exact=client_key, is_active__exact=True)
return config.CLIENT
def some_view(request, client_key):
client = get_client(client_key)
...
return some_response
# config.py
CLIENT = None
Multiple requests are processed by the same process and global variables like your CLIENT live as long, as process does. You shouldn't rely on global variables, when processing requests - use either local ones, when you need to keep a variable for the time of building response or put data into the database, when something must persist across multiple requests.
If you need to keep some value through the request you can either add it to thread locals (here you should some examples, that adds user info to locals) or simply pass it as a variable into other functions.
OK, just to make it slightly clearer (and in response to the comment by Felix), I'm posting the code that does what I needed. The whole problem arose from a fundamental misunderstanding on my part and I'm sorry for any confusion I might have caused.
import config
# This will be called once per request/view
def init_client(client_key):
config.CLIENT = get_object_or_404(Client, key__exact=client_key, is_active__exact=True)
# This might be called from other modules that are unaware of requests, views etc
def get_client():
return config.CLIENT