当前位置:网站首页>Use of local stack in flask

Use of local stack in flask

2022-06-25 22:33:00 Golden sunrise

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 .

原网站

版权声明
本文为[Golden sunrise]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202180954517222.html