I was reading the source code of the Werkzeug library in github and in one of the examples (Simplewiki to name it), in the application.py file there is function which binds the application to the current active context. I would like to know why this is necessary, or where can I find something that explains this?
The function is this:
def bind_to_context(self):
"""
Useful for the shell. Binds the application to the current active
context. It's automatically called by the shell command.
"""
local.application = self
And this is the part where the dispatcher binds the request.
def dispatch_request(self, environ, start_response):
"""Dispatch an incoming request."""
# set up all the stuff we want to have for this request. That is
# creating a request object, propagating the application to the
# current context and instanciating the database session.
self.bind_to_context()
request = Request(environ)
request.bind_to_context()
As far as I know, contexts in the Werkzeug is about separating environment between different threads. For example, contexts are very common thing in the Flask framework which is built on top of the Werkzeug. You can run Flask application in multi-threaded mode. In such case you'll have only one application object which is accessed by multiple threads simultaneously. Each thread requires a piece of data within the app for private usage. Storing such data is organized via thread's local storage. And this is called the context.
Related
I have a function which calls several API's and updates the database upon being called. I want to schedule the function to run daily at specific time.
Already tried flask_apscheduler and APScheduler which gives this error:
This typically means that you attempted to use functionality that needed an active HTTP request. Consult the documentation on testing for information about how to avoid this problem.
Any leads on this will be helpful.
You should:
Post the code where you define your flask application.
Specify how you try to access the app.
How you're calling the APIs.
Whether those APIs are 3rd party or part of your blueprint.
However, this is probably a context issue. I have come across a similar one with SQLAlchemy before.
You will need to somehow get access to your app, either by using app_context or by importing current_app from Flask and accessing the config.
Assuming you imported the app where your function is used, try this:
with app.app_context():
# call your function here
Refer to this document for more information: Flask Documentation
Another approach you can try, is passing your app configurations through a config class object.
You can define the jobs you want to schedule and pass a reference to your function inside.
Check this example from flask-apscheduler repository on GitHub.
I am trying to learn to make a variable available across method through a decorator function in Flask.
I read Flask request context documentation and wrote the following code, which works as intended.
a.py
_request_ctx_stack.top.current_identity = payload.get('sub')
b.py
current_identity = getattr(_request_ctx_stack.top, 'current_identity', None)
However flask-jwt solves this problem by introducing an additional local proxy like this:
a.py
from werkzeug.local import LocalProxy
current_identity = LocalProxy(lambda: getattr(_request_ctx_stack.top, 'current_identity', None))
_request_ctx_stack.top.current_identity = payload.get('sub')
b.py
from a import current_identity
Why? I read werkzeug context locals documentation and doesn't Flask already implements Werkzeug context locals for request object?
Is there any advantage of introducing LocalProxy?
The LocalProxy wraps the manual code you wrote for getting the value. Instead of needing that manual code everywhere you want to access current_identity, you access it as a proxy and it does the manual code for you.
It's most useful in libraries, where users wouldn't be expected to know how current_identity is set up, and would import the proxy to access it. The same applies to Flask itself: you're not expected to know how the request is set up, or where exactly it's stored, only that you access it by importing request.
A proxy is useful for data that is set up during and local to each request. If you used a true global variable, it would not behave the way you expect when multiple requests are being handled. See Are global variables thread safe in flask? How do I share data between requests?
I'm building an API with Flask in Google App Engine Python Standard Environment that is served through multiple domains.
The API can be used to store data and fetch data.
I want to use cloud datastore's multitenancy to store or fetch data only in a namespace determined by the domain from which the API is accessed.
The only way I can see to do this is to use google.appengine.api.namespace_manager to set the namespace either at request time or in a context manager at I/O time.
I wrote this context manager:
#contextmanager
def multitenancy_namespace(namespace):
original_namespace = namespace_manager.get_namespace()
if namespace:
new_namespace = to_namespace_safe_url(namespace)
namespace_manager.set_namespace(new_namespace)
yield
namespace_manager.set_namespace(original_namespace)
And it works as expected.
My worry is the scope of namespace_manager. I have not been able to find any documentation about this.
If my API is threaded and used simultaneously by >1000 users, assuming that the namespace as set by namespace_manager.set_namespace(...) is global, I would expect some collisions - data being stored in the wrong namespace because another request called set_namespace after the first request, but before the first request did its I/O.
I wrote a threaded test here that passes, which tells me that the scope of namespace is at least confined to individual threads (which is good enough for my Flask application).
But what is the context of namespace_manager? What does set_namespace actually do? Where is the namespace setting saved? Is there a use case where a namespace collision could happen?
If you look to the source code of namespace_manager.set_namespace(...) you'll see it does it by settings the namespace to an environment variable:
def set_namespace(namespace):
"""Set the default namespace for the current HTTP request.
Args:
namespace: A string naming the new namespace to use. A value of None
will unset the default namespace value.
"""
if namespace is None:
os.environ.pop(_ENV_CURRENT_NAMESPACE, None)
else:
validate_namespace(namespace)
os.environ[_ENV_CURRENT_NAMESPACE] = namespace
When a thread switches context the AppEngine backups & restores the environment variables as needed. They are guaranteed to be request bounded so it is opaque to user's code. I don't remember if there is docs for this, I think I've learned this at some forum thread.
The comment Set the default namespace for the current HTTP request is implicitly confirms this.
We use it at www.myclasses.org for few years and it's never been a problem.
So relax, you are safe to use it in multi-threaded environment!
Flask Web Development says:
from flask import request
#app.route('/')
def index():
user_agent = request.headers.get('User-Agent')
return '<p>Your browser is %s</p>' % user_agent
Note how in this view function request is used as if it was a global
variable. In reality, request cannot be a global variable if you
consider that in a multithreaded server the threads are working on
different requests from different clients at the same time, so each
thread needs to see a different object in request. Contexts enable
Flask to make certain variables globally accessible to a thread
without interfering with the other threads.
Understandable, but why not simply make request a thread-local variable? Under the hood, what exactly is request, and how is it different from a thread-local variable?
This was simply a design decision by Armin (the author of Flask). You could indeed rewrite Flask to operate as a thread-local, but that was not what he wanted to do here.
The idea of Flask (in general) is to keep things as simple as possible, and abstract a lot of thinking away. This is why a lot of Flask helpers are implemented as 'global variables': you don't really have to think about the meaning behind it, because each global is bound to the incoming request.
When setting up a Pyramid app and adding settings to the Configurator, I'm having issues understanding how to access information from request, like request.session and such. I'm completely new at using Pyramid and I've searched all over the place for information on this but found nothing.
What I want to do is access information in the request object when sending out exception emails on production. I can't access the request object, since it's not global in the __init__.py file when creating the app. This is what I've got now:
import logging
import logging.handlers
from logging import Formatter
config.include('pyramid_exclog')
logger = logging.getLogger()
gm = logging.handlers.SMTPHandler(('localhost', 25), 'email#email.com', ['email#email.com'], 'Error')
gm.setLevel(logging.ERROR)
logger.addHandler(gm)
This works fine, but I want to include information about the logged in user when sending out the exception emails, stored in session. How can I access that information from __init__.py?
Attempting to make request a global variable, or somehow store a pointer to "current" request globally (if that's what you're going to try with subscribing to NewRequest event) is not a terribly good idea - a Pyramid application can have more than one thread of execution, so more than one request can be active within a single process at the same time. So the approach may appear to work during development, when the application runs in a single thread mode and just one user accesses it, but produce really funny results when deployed to a production server.
Pyramid has pyramid.threadlocal.get_current_request() function which returns thread-local request variable, however, the docs state that:
This function should be used extremely sparingly, usually only in unit
testing code. it’s almost always usually a mistake to use
get_current_request outside a testing context because its usage makes
it possible to write code that can be neither easily tested nor
scripted.
which suggests that the whole approach is not "pyramidic" (same as pythonic, but for Pyramid :)
Possible other solutions include:
look at exlog.extra_info parameter which should include environ and params attributes of the request into the log message
registering exception views would allow completely custom processing of exceptions
Using WSGI middleware, such as WebError#error_catcher or Paste#error_catcher to send emails when an exception occurs
if you want to log not only exceptions but possibly other non-fatal information, maybe just writing a wrapper function would be enough:
if int(request.POST['donation_amount']) >= 1000000:
send_email("Wake up, we're rich!", authenticated_userid(request))