See: http://flask.pocoo.org/docs/appcontext/
There seems to be two main issues with this page.
[1] "The application setup state in which the application implicitly is on the module level."
[2] "In contrast, during request handling, a couple of other rules exist"
[3] "There is a third state which is sitting in between a little bit."
[4] "The main reason for the application鈥檚 context existence is that in the past a bunch of functionality was attached to the request context in lack of a better solution. Since one of the pillar鈥檚 of Flask鈥檚 design is that you can have more than one application in the same Python process."
[5] "To make an application context there are two ways."
[6] "The context is typically used to cache resources on there that need to be created on a per-request or usage case."
I'm willing to draft a rewrite myself since I need to understand this anyway for my current project.
I think it would be helpful if (1) others could look it over and tell me if any points are missing, outdated, or incorrect (since it seems to have been somewhat neglected) and (2) if there are any existing explanations which others have found useful for making sense of application contexts which I could use as a reference or direct people toward in a further reading section.
I think the page should at least refer more prominently to http://werkzeug.pocoo.org/docs/local/, as some basic concepts (thread locals) are explained there.
I agree. Studying thread locals and context locals was helpful. Continuing on that point, I also think the Request context page should be arranged before the Application context page, since (1) it's easier to understand and (2) the application context was a product of issues with the request context.
Can someone provide me a definition for an application context? I having trouble grasping the term. The two docstrings on Flask.app_context and AppContext are not the clearest.
Binds the application only. For as long as the application is bound to the current context the :data:
flask.current_apppoints to that application. An application context is automatically created when a request context is pushed if necessary. -Flask.app_contextThe application context binds an application object implicitly to the current thread or greenlet, similar to how the :class:
RequestContextbinds request information. The application context is also implicitly created if a request context is created but the application is not on top of the individual application context. -AppContext
original == original, it is that proxy == original, but in Python it's never going to be that proxy is original.flask.current_app is a thread local which proxies the application whose application context is currently active.flask.current_app is proxying the app X.Awkward formulation, but i think that sums it up. I am a bit new to this myself, so any corrections are appreciated.
See werkzeug/local.py for all of this.
I am trying to write the abstract, starting from context locals. In @mitsuhiko's 2011 Pycon talk "Opening the Flask" he argued that context-locals should appear everywhere or nowhere. [1] This of course omits the idea of using context-locals sometimes, as they do in Django (where it is mostly threaded through functions, but occasionally introspection is possible, as in internationalization). Is there an archive of this argument somewhere I can find? I couldn't find anything in the mailing list.
[1] http://blip.tv/pycon-us-videos-2009-2010-2011/pycon-2011-opening-the-flask-4896892 at 11:25
Does anyone know why we use current_app to refer to the current app, but request to refer to the current request (i.e., it's inconsistent)?
I'd guess because there'd be a naming collision with the app variable you're using to register routes.
l second that a rewrite would be great. Perhaps some inspiration can be had from this SO answer:
https://stackoverflow.com/questions/20036520/what-is-the-purpose-of-flasks-context-stacks
I think one reason people are confused is because there are app and request contexts and it's not clear why they are there and what the lifetime is. That might need some clarification in the docs.
:+1: As a newcomer trying to make sense of things, this is very very hard.
The appcontext definitely needs some clarification in the docs. The docs say that the appcontext "will not be shared between requests." However, I don't really see the point of separate teardown_request and teardown_appcontext functions if both the request context and the appcontext are torn down with every request.
I believe that the appcontext is not shared between different threads, but is shared between different requests in the same thread. This is consistent with some of the documentation (and it's consistent with a sensible design.) Reading through docstrings I've seen contradictory information in various places.
@lukeschlather The appcontext is _not_ shared between requests, for the simple reason that persisting it between requests would amount to global state. The point is to have flask.g available in scripts as well, where no HTTP request (and therefore no request context) is available. Having flask.g bound to the request context makes no sense because there's nothing there that would really depend on a HTTP request.
The docs may be confusing but they're not technically wrong. If you find logical contradictions please do point those out, because even if the docs fail to explain those concepts well, they should at least not contradict themselves.
I think that document in question would gain from adding a top down perspective on "why" specific design decisions were made. This top down perspective would involve explaining the physical constraints involved in solving the problem of delivering a specific internet service, e.g., a single version of an app based on Flask. With that understanding to build on, the answers should fall into place like a jigsaw puzzle.
We know that the app may be distributed as identical "clone" processes each on a different physical server(1), each clone running exactly the same software logic and having exactly the same configuration - let us say the same DNA. The reason for this is scalability - client traffic might suddenly increase, servers might suddenly fail, yet the system needs to respond seamlessly so that the clients do not experience delays. Therefore a design decision is made: a process should never store any "session" state necessary to complete a client-server session. (This is one the REST requirements). This means that for a specific client session, each request from that client session can be routed to an arbitrary clone, doesn't have to be routed to the same clone for each request in a session, and the server clones don't have communicate DIRECTLY to each other about that client session state. Of course, a clone can pass state information to the client, for the client to pass that same state information onto the next serving clone in the session sequence. (1: Arbitrarily assuming there is no reason to run multiple clone processes on the same physical server, but perhaps I'm wrong).
Now the reason for the setup and teardown of the so-called "context global" variables app_ctx, g, request, and session at the start and end of a request is clear: that clone might never service that client session again, so the memory resources are reclaimed for other use. Note: "Global" is not really a specific enough term and could cause confusion. The actual scope of these variables is limited to the time span of a single request and the physical span of a single thread in a single process on a single server.
Although app_ctx, g, request, and session share the same single request scope, they are set and read by different characters for different purposes:
It is stated that multiple non-identical Flask apps my be running in the same process space. I guess this has something to do with optimizing load balancing but I don't have any specific knowledge about what problem this paradigm solves, so I'll just take it at face value that it happens. In any event, that paradigm is not the one necessitating the so-called "context global" variables app_ctx, g, request, and session to be set up and torn down with each client request.
Also, the paradigm of accessing the application from a shell is unrelated to production usage of serving clients. It is just a convenient way to run scripts for things like migrating a database and testing. The existing structure of "g" variable happens to be available and useful due to the clever design of Flask, but there is no deep meaning beyond that. There would have been other less clever ways to chieve the same result.
In conclusion, sometimes the big picture takes too long to explain, and giving a simplified recipe is more pragmatic. But it can only go far, and it will eventually lead to confusion and dogma. It's like the difference between using the bible to try to explain the existence of the universe, and using your understanding of the universe to explain the existence of the bible.
EDIT: Sorry for the noise. I seem to have come to false conclusions regarding the app context, where I thought it was surviving between requests. Which clearly is not the case, so my confusion lies else where (and also in my clearly limited understanding of the app context). It actually was the upgrade note that this change should be transparent for me as user that got me on the right track again.
My apologies.
The parts below kept for the record where I was wrong..
--
I've not spent the time reading up on the history on this issue, so may reiterate points. Here is what I found confusing in the documentation regarding the flask.g object:
The application context is created and destroyed as necessary. It never moves between threads and it will not be shared between requests
Since https://github.com/pallets/flask/commit/1949c4a9abc174bf29620f6dd8ceab9ed3ace2eb it is shared between requests.
The context is typically used to cache resources that need to be created on a per-request or usage case.
Still not per-request safe, as this paragraph suggests.
And in the api documentation for App Globals, there is this paragraph:
To share data that is valid for one request only from one function to another, a global variable is not good enough because it would break in threaded environments. Flask provides you with a special object that ensures it is only valid for the active request and that will return different values for each request. In a nutshell: it does the right thing, like it does for request and session.
This clearly states the previous functionality when the g object was on the request context stack.
The _only_ hint (Edit: oh, except in the changelog and upgrade notes) that it is not a per-request safe object any more, is this passage, which was added in the referenced commit:
Starting with Flask 0.10 this is stored on the application context and no longer on the request context which means it becomes available if only the application context is bound and not yet a request.
And as it is not super clear (what is the consequence of being on the app context, with regard to per-request data), and contradicts all other documentation regarding this object, one may come to the conclusion that it is not accurate.
Edit: the upgrade notes state that this change should be transparent to you (as user). How is it transparent? If I put the logged in user on flask.g.userid in one request and the next request comes from another client that is not logged in there is still the flask.g.userid from the previous request.
I hope the tone comes across as constructive feedback, and nothing else. I find flask to be a great library and want it all the best. Cheers for all the work so far!
Most helpful comment
:+1: As a newcomer trying to make sense of things, this is very very hard.