4 Context variable
Take on the content of the previous article . When a request comes , except request Encapsulated as a global variable , Three other variables are also encapsulated into global variables , That's it current_app、g、session. above 4 The reason why a variable can be used , Because the program context is in effect .
The concept of context is very common , For example, the context of the current process will be saved during process switching , Restore the context of the active process . I've seen the explanation of context transparency, which means that the so-called context is the running environment , Restoring the context is to restore the running environment .
stay Flask There are two contexts : Program context
and Request context
. When a request comes ,Flask Will activate both contexts , among request Is to get... In the context of the request .
Variable name | Context | explain |
---|---|---|
current_app | Application context | The program instance of the currently active program |
g | Application context | Objects used as temporary storage when processing requests . This variable is reset on every request |
request | Request context | Request object , Encapsulates the HTTP What's in the request |
session | Request context | The user's session , It is used to store the information needed between requests “ remember ” Dictionary |
The lifecycle of the context in the request
Flask Before distributing the request, the program context (AppContext) Push into the application local stack , The request context (RequestContext) Push into the request local stack . After the request processing is completed, the two contexts are stacked separately .
After the program context is stacked , You can use... In the view function current_app and g Variable ; Allied , After the request context is pushed , You can use request and session Variable .
say concretely : The request context is saved in _request_ctx_stack
, The program context is saved in _app_ctx_stack
. When a request comes , Request context object RequestContext
, Program context object AppContext
Will be stacked accordingly .
Flask Classic mistakes
If we use these variables without activating the program context or request context, it will lead to a Flask Classic mistake .RuntimeError: Working outside of application context.
such as :
from flask import Flask, current_app
app = Flask(__name__)
print(current_app.name)
In the example above, print current_app Name , But not in the view function , That is, no request came . Then this program will report an error :
That's why current_app
It must be when the request comes , The request context and program context can only be used after they are activated . The above code does not request the arrival , therefore current_app
Out of commission .
Manual stack program context
In order to be able to use without a request Flask Project configuration , Documents, etc. , You can manually stack the program context .
from flask import Flask, current_app
app = Flask(__name__)
with app.app_context():
print(current_app)
print(current_app.config) # Print flask Project configuration
<Flask 'manual_push'>
<Config {'ENV': 'production', 'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': None, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(days=31), 'USE_X_SENDFILE': False, 'SERVER_NAME': None, 'APPLICATION_ROOT': '/', 'SESSION_COOKIE_NAME': 'session', 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_SAMESITE': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': None, 'TRAP_BAD_REQUEST_ERRORS': None, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': False, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, 'MAX_COOKIE_SIZE': 4093}>
Why should request context and program context be separated
stay flask0.1 The request context and the program context are stored in the same stack , Why is it separated from the back ?
For the sake of non web Applications . The so-called non web An application is when no request comes , You also need to use the scenario of program context , The typical representative is flask shell. Dealing with some database imports , There is no network request in scenarios such as script , There is no request context or program context . therefore current_app Not to be used , Such as configuration information 、orm Databases, etc. are not available . In order to be able to use the application context without the arrival of the request , So separate the program context from the request context , Then use the manual stack program context to facilitate the use of flask Features provided . That is, the manual stacking analyzed above .
Why use the stack to store context objects
When I learned this, I actually had a question , Why do request context objects and program context objects need to be saved on the local stack ? Can't you use local threads ?
The explanation given online is flask Process two at the same time through middleware app The program , Two app Your requests will exist at the same time , Using the local stack can let each request find its own data . But according to flask The server-side model , At the same time , A thread processes only one request , There will never be multiple requests processed at the same time , The context can also be saved with local threads , So what exactly makes flask Using the data structure of local stack ?
Flask Processing model
First of all flask Service processing model
flask There are two startup modes , They are single thread and multi thread . Single thread startup means that requests are processed in only one thread , When the last request did not return , The next request needs to wait ; The arrival of each request in a multithreaded request will not be blocked , There will be multiple threads to provide processing . The default is multithreading
Single process
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world(num):
return f"Hello world!"
if __name__ == '__main__':
app.run()
Multi process
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world(num):
return f"Hello world!"
if __name__ == '__main__':
app.run(processes=True)
But whether it's multi process startup or single process startup , The same thread can only process one request at a time , And because of local threading technology ( The previous article introduced local threading technology Flask Elegant transmission of request data in ) In other words, there is only one at the same time request object , So why flask preservation request Object using a local stack instead of a local thread ?
The answer to that question is : When the program context is manually stacked , You can stack multiple program contexts . In this way, there will be multiple program contexts at the same time , In order to get the correct program context , You need to use the first in and last out structure of stack .
If you don't understand the reason, it doesn't matter , The explanation can be found in the following program .
import time
from flask import Flask, current_app
app1 = Flask('app01')
app2 = Flask('app02')
def do_something():
print("app1 Pressing stack ------------------------------------")
with app1.app_context():
time.sleep(5)
print("app2 Pressing stack ------------------------------------")
with app2.app_context():
pass # current_app Is the program context , The last top element is app1, When app2 What you get when pushed is app2
print("app2 is Out of the stack -------------------------------------")
# When app2 After leaving the stack , The top element of the stack becomes app1, At this time, the top element of the stack is obtained
do_something()
At the same time Flask After the debugging context is printed into the program stack
When app1 After entering the stack ,_app_ctx_stack
There is only one element in , Namely app1, Now visit current_app Namely app1;
When app2 After entering the stack ,_app_ctx_stack
There are two elements in , And the top of the stack is app2. Now visit current_app Namely app2;
When app2 After leaving the stack ,_app_ctx_stack
There is one element left in , Namely app1, Then visit current_app Namely app1.
It is through this stack data structure , Let the handler get the information in its own program context current_app.
Summary
Both the program context and the request context are stored in the local stack , Because there are multiple context nesting when manually stacking , Therefore, the data structure such as stack needs to keep the latest context and get it first .