Noelia  Graham

Noelia Graham

1660230900

Fonctionnement Des Contextes D'application Et De Demande Dans Flask

L'objectif de cet article est de clarifier le fonctionnement des contextes d'application et de demande dans Flask.

Objectifs

À la fin de cet article, vous devriez être en mesure d'expliquer :

  1. Comment Flask gère l'objet de requête et en quoi cela diffère des autres frameworks Web
  2. Quel est le contexte de l'application et de la demande ?
  3. Quelles données sont stockées dans les contextes d'application et de demande
  4. Comment utiliser current_app, test_request_contextet test_clientavec les contextes corrects

Vous devriez également être en mesure de corriger l'erreur suivante :

RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().

Contextes dans Flask

Contrairement à Django et à d'autres frameworks Web, les fonctions de vue Flask n'acceptent pas un objet de requête contenant des métadonnées sur la requête HTTP.

Django Exemple :

def users(request):
    if request.method == 'POST':
         # Save the form data to the database
         # Send response
   else:
         # Get all users from the database
         # Send response

Avec Flask, vous importez dans l'objet de requête comme ceci :

from flask import request

@app.route('/users', methods=['GET', 'POST'])
def users():
    if request.method == 'POST':
         # Save the form data to the database
         # Send response
    else:
         # Get all users from the database
         # Send response

Dans l'exemple Flask, l'objet de requête ressemble, se sent et agit comme une variable globale, mais ce n'est pas le cas.

Si l'objet de requête était une variable globale, vous ne pourriez pas exécuter une application Flask multithread car les variables globales ne sont pas thread-safe.

Au lieu de cela, Flask utilise des contextes pour faire en sorte qu'un certain nombre d'objets "agissent" comme des globals uniquement pour le contexte particulier (un thread, un processus ou une coroutine) utilisé. Dans Flask, cela s'appelle un context-local .

Les paramètres locaux de contexte sont similaires mais finalement différents de l' implémentation locale des threads de Python pour stocker des données spécifiques à un thread. L'implémentation de Flask est plus générique afin de permettre aux travailleurs d'être des threads, des processus ou des coroutines.

Données stockées dans des contextes Flask

Lorsqu'une requête est reçue, Flask fournit deux contextes :

Le contexteLa descriptionObjets disponibles
ApplicationAssure le suivi des données au niveau de l'application (variables de configuration, enregistreur, connexion à la base de données)current_app,g
DemandeAssure le suivi des données au niveau de la demande (URL, méthode HTTP, en-têtes, données de demande, informations de session)request,session

Il convient de noter que chacun des objets ci-dessus est souvent appelé "proxies". Cela signifie simplement qu'ils sont des mandataires des saveurs globales des objets. Pour en savoir plus, consultez le deuxième article de cette série.

Flask gère la création de ces contextes lorsqu'une requête est reçue. Ils peuvent prêter à confusion car vous n'avez pas toujours accès à un objet particulier en fonction de l'état dans lequel se trouve votre application.

Regardons quelques exemples.

Exemple de contexte d'application

Supposons que vous ayez l'application Flask suivante :

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Welcome!'

if __name__ == '__main__':
    app.run()

Voyons d'abord comment utiliser l' objet current_app pour accéder au contexte Application.

Dans le shell Python, si vous essayez d'accéder à l' current_app.configobjet en dehors d'une fonction d'affichage, vous devriez voir l'erreur suivante :

$ python
>>> from flask import current_app
>>> current_app.config

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "werkzeug/local.py", line 347, in __getattr__
    return getattr(self._get_current_object(), name)
  File "werkzeug/local.py", line 306, in _get_current_object
    return self.__local()
  File "flask/globals.py", line 52, in _find_app
    raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().  See the
documentation for more information.

Pour accéder aux objets exposés par les contextes Application et Requête en dehors d'une fonction d'affichage, vous devez d'abord créer le contexte approprié :

# without a context manager
$ python

>>> from app import app
>>> from flask import current_app
>>>
>>> app_ctx = app.app_context()
>>> app_ctx.push()
>>>
>>> current_app.config["ENV"]
'production'
>>> app_ctx.pop()
>>>
# with a context manager
$ python

>>> from app import app
>>> from flask import current_app
>>>
>>> with app.app_context():
...     current_app.config["ENV"]
...
'production'
>>>

Exemple de contexte de demande

Vous pouvez utiliser la méthode test_request_context pour créer un contexte de requête :

# without a context manager
$ python

>>> from app import app
>>> from flask import request
>>>
>>> request_ctx = app.test_request_context()
>>> request_ctx.push()
>>>
>>> request.method
'GET'
>>>
>>> request.path
'/'
>>>
>>> request_ctx.pop()
>>>
# with a context manager
$ python

>>> from app import app
>>> from flask import request
>>>
>>> with app.test_request_context('/'):
...     request.method
...     request.path
...
'GET'
'/'
>>>

test_request_contextest généralement utilisé pendant les tests lorsque vous souhaitez utiliser des données de requête sans la surcharge d'une requête complète.

Exemple de test

Le moment le plus courant pour rencontrer des problèmes avec le contexte de l'application et de la demande est lorsque votre application est en cours de test :

import pytest
from flask import current_app

from app import app


@pytest.fixture
def client():
    with app.test_client() as client:
        assert current_app.config["ENV"] == "production"  # Error!
        yield client


def test_index_page(client):
   response = client.get('/')

   assert response.status_code == 200
   assert b'Welcome!' in response.data

Une fois exécutés, les tests échoueront dans le projecteur :

$ pytest
________________________ ERROR at setup of test_index_page _____________________

@pytest.fixture
def client():
    with app.test_client() as client:
>       assert current_app.config["ENV"] == "production"
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def _find_app():
        top = _app_ctx_stack.top
        if top is None:
>           raise RuntimeError(_app_ctx_err_msg)
E           RuntimeError: Working outside of application context.
E
E           This typically means that you attempted to use functionality that needed
E           to interface with the current application object in some way. To solve
E           this, set up an application context with app.app_context().  See the
E           documentation for more information.
================================= 1 error in 0.13s =================================

Pour corriger, créez un contexte d'application avant d'accéder current_app:

import pytest
from flask import current_app

from app import app


@pytest.fixture
def client():
    with app.test_client() as client:
        with app.app_context():  # New!!
            assert current_app.config["ENV"] == "production"
        yield client


def test_index_page(client):
   response = client.get('/')

   assert response.status_code == 200
   assert b'Welcome!' in response.data

Sommaire

Pour résumer, utilisez les objets suivants dans les fonctions d'affichage, les commandes CLI et les fonctions de test :

ObjetLe contexteErreur communeLa solution
current_appContexte d'applicationTravailler en dehors du contexte de l'applicationwith app.app_context():
gContexte d'applicationTravailler en dehors du contexte de l'applicationwith app.test_request_context('/'):
requestContexte de la demandeTravailler en dehors du contexte de la demandewith app.test_request_context('/'):
sessionContexte de la demandeTravailler en dehors du contexte de la demandewith app.test_request_context('/'):

Les méthodes suivantes doivent être utilisées lors des tests :

Méthode du flaconLa description
test_clientClient de test pour l'application Flask
test_request_contextPousser le contexte de la demande pour les tests

Source :  https://testdrive.io

#flask 

What is GEEK

Buddha Community

Fonctionnement Des Contextes D'application Et De Demande Dans Flask
Shayna  Lowe

Shayna Lowe

1660048200

Fonctionnement Des Contextes D'application Et De Demande Dans Flask

Cet article explore le fonctionnement des contextes Application et Request dans Flask.

Objectifs

À la fin de cet article, vous devriez être en mesure d'expliquer :

  1. Qu'est-ce qu'un contexte
  2. Quelles données sont stockées dans les contextes d'application et de demande
  3. Les étapes nécessaires au traitement des contextes Application et Request lorsqu'une requête est traitée dans Flask
  4. Utilisation des proxys vers le contexte Application et Request
  5. Comment utiliser les proxys current_appet dans les fonctions d'affichagerequest
  6. Qu'est-ce qu'un contexte-local ?

Qu'est-ce qu'un contexte ?

Pour exécuter le code que vous écrivez, il a besoin de données à traiter. Ces données peuvent être des données de configuration, des données d'entrée, des données de la base de données, etc.

Les contextes sont utilisés pour garder une trace des données dont votre code a besoin pour s'exécuter.

Dans Flask, les contextes sont utilisés pour fournir les données nécessaires au traitement des requêtes et des commandes de l'interface de ligne de commande (CLI).

Bien que cet article se concentre sur le traitement des requêtes, les concepts présentés s'appliquent également aux commandes CLI.

Traitement des demandes

Commençons par la façon dont une demande est traitée à partir d'un haut niveau :

Diagramme du serveur Web, du serveur WSGI et de l'application Flask

Ainsi, une requête est envoyée du navigateur au serveur Web (comme Nginx ou Apache) pour demander une URL spécifique ('/' URL dans le schéma ci-dessus). Le serveur Web achemine ensuite cette demande vers un serveur WSGI pour traitement.

WSGI, qui signifie Web Server Gateway Interface, est une interface entre un serveur Web et une application Web basée sur Python. C'est nécessaire car un serveur Web ne peut pas communiquer directement avec une application Python. Pour en savoir plus, consultez WSGI .

Le serveur WSGI demande à l'application Flask de traiter la demande.

L'application Flask génère une réponse, qui est renvoyée au serveur WSGI, puis au serveur Web et, finalement, au navigateur Web.

Ces étapes décrivent le cycle demande-réponse, qui est une fonction clé du traitement d'une demande via un serveur Web, un serveur d'application WSGI et une application Web.

Contextes dans Flask

Lorsqu'une requête est reçue, Flask fournit deux contextes :

Le contexteLa descriptionObjets disponibles
ApplicationAssure le suivi des données au niveau de l'application (variables de configuration, enregistreur, connexion à la base de données)current_app,g
DemandeAssure le suivi des données au niveau de la demande (URL, méthode HTTP, en-têtes, données de demande, informations de session)request,session

Il convient de noter que chacun des objets ci-dessus est souvent appelé "proxies". Cela signifie simplement qu'ils sont des mandataires des saveurs globales des objets. Nous approfondirons cela sous peu.

Flask gère la création de ces contextes lorsqu'une requête est reçue. Ils peuvent prêter à confusion car vous n'avez pas toujours accès à un objet particulier en fonction de l'état dans lequel se trouve votre application.

Schéma de présentation

Le schéma suivant illustre le traitement des contextes lors du traitement d'une requête :

Traitement des demandes - Aperçu

Il se passe beaucoup de choses dans ce diagramme, nous allons donc parcourir chaque étape en détail.

Étape 1 - Serveurs Web et WSGI

Tout commence lorsqu'une requête est reçue par le serveur Web :

Traitement de la demande - Étape 1

Le travail du serveur Web consiste à acheminer les requêtes HTTP entrantes vers un serveur WSGI .

Apache et Nginx sont deux serveurs Web courants tandis que Gunicorn , uWSGI et mod_wsgi sont des serveurs WSGI populaires.

Il convient de noter que même si Flask Development Server est un serveur WSGI, il n'est pas destiné à être utilisé en production.

Étape 2 - Travailleur

Afin de traiter la requête, le serveur WSGI génère un worker pour gérer la requête :

Traitement de la demande - Étape 2

Le travailleur peut être un thread, un processus ou une coroutine. Par exemple, les travailleurs seraient des threads si vous utilisez Flask Development Server avec sa configuration par défaut.

Si vous souhaitez en savoir plus sur les différences entre les threads, le multitraitement et l'asynchronisme dans Python, consultez l' article Accélérer Python avec la concurrence, le parallélisme et l'asynchronie et la vidéo Concurrence dans Python .

Pour cette explication, le type de travailleur n'est pas important ; le point clé à propos du travailleur est qu'il traite une demande à la fois (d'où la nécessité de plus d'un travailleur).

Étape 3 - Contextes

Une fois l'exécution basculée vers l'application Flask, Flask crée les contextes Application et Request et les pousse sur leurs piles respectives :

Traitement de la demande - Étape 3

Pour passer en revue, le contexte d'application stocke les données au niveau de l'application, telles que les variables de configuration, la connexion à la base de données et l'enregistreur. Le contexte Request, quant à lui, stocke les données spécifiques à la requête qui doivent être traitées afin de générer une réponse.

Cela peut être surprenant à voir, mais les deux piles sont implémentées en tant qu'objets globaux (cela deviendra plus clair dans la section suivante).

Étape 4 - Procurations

Maintenant que l'application Flask est prête à traiter les données (dans la fonction d'affichage) et que les données sont prêtes dans les piles de contexte d'application et de demande, nous avons besoin d'un moyen de connecter ces deux éléments... des proxys à la rescousse !

Traitement de la demande - Étape 4

Les proxys sont utilisés par les fonctions de vue pour accéder aux contextes Application (stockés dans la pile de contexte Application) et Request (stockés dans la pile de contexte Request) :

  • current_app- proxy vers le contexte d'application pour le travailleur
  • request- proxy vers le contexte de la requête pour le travailleur

À première vue, cette séquence peut sembler déroutante, car la fonction de vue semble accéder aux objets globaux (piles de contexte d'application et de demande) via les proxys. Si tel était le cas, cette opération serait problématique, car elle n'est pas thread-safe. Vous pouvez également penser que ces piles (en tant qu'objets globaux) pourraient être accessibles par n'importe quel travailleur, ce qui serait un problème de sécurité.

Cependant, cette conception est l'une des grandes fonctionnalités de Flask... les piles sont implémentées en tant qu'objets contextuels .

Pour en savoir plus sur les proxys, consultez les notes sur les proxys de la documentation Flask et l' article sur le modèle de proxy .

Locaux de contexte

Python a un concept de données locales de thread pour stocker des données spécifiques à un thread, qui sont à la fois "thread-safe et thread-unique". En d'autres termes, chaque thread pourra accéder aux données de manière sécurisée et les données sont toujours uniques au thread spécifique.

Flask implémente un comportement similaire (context-locals), mais de manière plus générique pour permettre aux travailleurs d'être des threads, des processus ou des coroutines.

Les contextes locaux sont en fait implémentés dans Werkzeug , qui est l'un des packages clés qui comprend Flask. Pour plus de simplicité, nous ferons référence à Flask lors de l'examen des contextes locaux.

Lorsque les données sont stockées dans un objet local au contexte, les données sont stockées de manière à ce qu'un seul travailleur puisse les récupérer. Par conséquent, si deux travailleurs distincts accèdent à un objet contextuel local, ils récupèrent chacun leurs propres données spécifiques qui sont uniques à chaque travailleur.

Un exemple utilisant un objet local contextuel sera présenté dans la section suivante.

Pour résumer, les proxies current_appet requestsont disponibles dans chaque fonction de vue et ils sont utilisés pour accéder aux contextes à partir de leurs piles respectives, qui sont stockées en tant qu'objets locaux au contexte.

L'utilisation de 'pile' dans le contexte des piles de contexte Application et Demande rend ce concept encore plus déroutant qu'il ne l'est déjà. Ces "piles" ne stockent généralement pas plus d'un seul contexte.

La structure de données utilisée est une pile car il existe des scénarios très avancés (par exemple, des redirections internes ) qui nécessitent plus d'un élément.

Avantage des proxys dans Flask

Si vous deviez créer votre propre framework Web à partir de zéro, vous pourriez envisager de transmettre les contextes d'application et de demande dans chaque fonction d'affichage comme ceci :

@app.route('/add_item', methods=['GET', 'POST'])
def add_item(application_context, request_context):  # contexts passed in!
   if request_context.method == 'POST':
       # Save the form data to the database
       ...
       application_context.logger.info(f"Added new item ({ request_context.form['item_name'] })!")
       ...

En fait, un certain nombre de frameworks Web fonctionnent de la sorte (y compris Django ).

Cependant, Flask fournit les proxies current_appet requestqui finissent par ressembler à des variables globales pour une fonction de vue :

from flask import current_app, request

@app.route('/add_item', methods=['GET', 'POST'])
def add_item():
   if request.method == 'POST':
       # Save the form data to the database
       ...
       current_app.logger.info(f"Added new item ({ request.form['item_name'] })!")
       ...

En utilisant cette approche, la fonction de vue n'a pas besoin des contextes passés en tant qu'arguments ; cette approche permet une définition simplifiée de la fonction de vue. Cela peut prêter à confusion car vous n'avez pas toujours accès aux proxys current_appet request, selon l'état dans lequel se trouve votre application.

RAPPEL : Les proxies current_appet requestne sont pas réellement des variables globales ; ils pointent vers des objets globaux qui sont implémentés en tant que contextes locaux, de sorte que les proxys sont toujours uniques à chaque travailleur.

Étape 5 - Nettoyer

Une fois la réponse générée, les contextes Request et Application sont extraits de leurs piles respectives :

Traitement de la demande - Étape 5

Cette étape nettoie les piles.

La réponse est ensuite renvoyée au navigateur web, qui complète le traitement de cette requête.

Contexte-Locals

Les objets contextuels locaux sont implémentés à l'aide d'objets locaux , qui peuvent être créés comme suit :

$ python

>>> from werkzeug.local import Local
>>> data = Local()
>>> data.user = 'pkennedy@hey.com'

Chaque contexte (c'est-à-dire, les 'travailleurs' discutés dans la section précédente) peut accéder à un Localobjet pour le stockage de données unique au contexte. Les données consultées sont propres au contexte et ne sont accessibles que par ce contexte.

Les objets LocalStack sont similaires aux Localobjets, mais conservent une pile d'objets à autoriser push()et d' pop()opérations.

Dans la section précédente, nous avons appris comment la pile de contexte d'application et la pile de contexte de demande sont utilisées lorsqu'une demande est traitée dans Flask. Ces piles sont implémentées en tant LocalStackqu'objets dans la mémoire globale de Flask.

Pour aider à solidifier le fonctionnement des contextes locaux, parcourons un exemple en créant un LocalStackobjet dans la mémoire globale, puis en y accédant par trois threads distincts :

Exemple LocalStack avec trois threads

Voici le script complet pour cet exemple :

"""
Example script to illustrate how a global `LocalStack` object can be used
when working with multiple threads.
"""
import random
import threading
import time

from werkzeug.local import LocalStack

# Create a global LocalStack object for storing data about each thread
thread_data_stack = LocalStack()


def long_running_function(thread_index: int):
    """Simulates a long-running function by using time.sleep()."""

    thread_data_stack.push({'index': thread_index, 'thread_id': threading.get_native_id()})
    print(f'Starting thread #{thread_index}... {thread_data_stack}')

    time.sleep(random.randrange(1, 11))

    print(f'LocalStack contains: {thread_data_stack.top}')
    print(f'Finished thread #{thread_index}!')
    thread_data_stack.pop()


if __name__ == "__main__":
    threads = []

    # Create and start 3 threads that each run long_running_function()
    for index in range(3):
        thread = threading.Thread(target=long_running_function, args=(index,))
        threads.append(thread)
        thread.start()

    # Wait until each thread terminates before the script exits by
    # 'join'ing each thread
    for thread in threads:
        thread.join()

    print('Done!')

Ce fichier crée un LocalStackobjet ( thread_data_stack) pour stocker les données de chacun des threads qui seront créés.

thread_data_stackimite la pile de contexte d'application ou la pile de contexte de demande dans Flask.

Le long_running_functionest exécuté dans chacun des threads :

def long_running_function(thread_index: int):
    """Simulates a long-running function by using time.sleep()."""

    thread_data_stack.push({'index': thread_index, 'thread_id': threading.get_native_id()})
    print(f'Starting thread #{thread_index}... {thread_data_stack}')

    time.sleep(random.randrange(1, 11))

    print(f'LocalStack contains: {thread_data_stack.top}')
    print(f'Finished thread #{thread_index}!')
    thread_data_stack.pop()

Cette fonction envoie des données sur le thread à l' thread_data_stackobjet dans la mémoire globale :

thread_data_stack.push({'index': thread_index, 'thread_id': threading.get_native_id()})

Cette opération imite le contexte d'application ou de demande poussé vers leur pile respective.

Une fois la time.sleep()fonction terminée, les données du thread_data_stacksont accessibles :

print(f'LocalStack contains: {thread_data_stack.top}')

Cette opération imite l'utilisation des proxys app_contextet request, car ces proxys accèdent aux données au sommet de leur pile respective.

A la fin de la fonction, les données sont extraites du thread_data_stack:

thread_data_stack.pop()

Cette opération imite l'extraction du contexte Application ou Request de leur pile respective.

Lorsque le script est exécuté, il démarre 3 threads :

# Create and start 3 threads that each run long_running_function()
for index in range(3):
    thread = threading.Thread(target=long_running_function, args=(index,))
    threads.append(thread)
    thread.start()

Et joinchaque thread pour que le script attende que chaque thread termine son exécution :

# Wait until each thread terminates before the script exits by
# 'join'ing each thread
for thread in threads:
    thread.join()

Exécutons ce script pour voir ce qui se passe :

$ python app.py

Starting thread #0... <werkzeug.local.LocalStack object at 0x109cebc40>
Starting thread #1... <werkzeug.local.LocalStack object at 0x109cebc40>
Starting thread #2... <werkzeug.local.LocalStack object at 0x109cebc40>
LocalStack contains: {'index': 0, 'thread_id': 320270}
Finished thread #0!
LocalStack contains: {'index': 1, 'thread_id': 320271}
Finished thread #1!
LocalStack contains: {'index': 2, 'thread_id': 320272}
Finished thread #2!
Done!

Ce qui est vraiment intéressant à propos de chaque thread, c'est qu'ils pointent tous vers le même LocalStackobjet en mémoire :

Starting thread #0... <werkzeug.local.LocalStack object at 0x109cebc40>
Starting thread #1... <werkzeug.local.LocalStack object at 0x109cebc40>
Starting thread #2... <werkzeug.local.LocalStack object at 0x109cebc40>

Lorsque chaque thread accède à thread_data_stack, l'accès est unique à ce thread ! C'est la magie de LocalStack(et Local) - ils permettent un accès contextuel unique :

LocalStack contains: {'index': 0, 'thread_id': 320270}
LocalStack contains: {'index': 1, 'thread_id': 320271}
LocalStack contains: {'index': 2, 'thread_id': 320272}

L'accès à thread_data_stackest également thread-safe, contrairement à l'accès à la mémoire globale typique.

Conclusion

L'un des aspects puissants (mais déroutants) de Flask est la manière dont les contextes Application et Request sont gérés. Espérons que cet article ait apporté des éclaircissements sur ce sujet !

Les contextes Application et Request fournissent les données nécessaires lors du traitement des requêtes ou des commandes CLI. Assurez-vous d'utiliser les proxys current_appet requestpour accéder au contexte d'application et au contexte de demande.

Source :  https://testdrive.io

#flask #python 

Noelia  Graham

Noelia Graham

1660230900

Fonctionnement Des Contextes D'application Et De Demande Dans Flask

L'objectif de cet article est de clarifier le fonctionnement des contextes d'application et de demande dans Flask.

Objectifs

À la fin de cet article, vous devriez être en mesure d'expliquer :

  1. Comment Flask gère l'objet de requête et en quoi cela diffère des autres frameworks Web
  2. Quel est le contexte de l'application et de la demande ?
  3. Quelles données sont stockées dans les contextes d'application et de demande
  4. Comment utiliser current_app, test_request_contextet test_clientavec les contextes corrects

Vous devriez également être en mesure de corriger l'erreur suivante :

RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().

Contextes dans Flask

Contrairement à Django et à d'autres frameworks Web, les fonctions de vue Flask n'acceptent pas un objet de requête contenant des métadonnées sur la requête HTTP.

Django Exemple :

def users(request):
    if request.method == 'POST':
         # Save the form data to the database
         # Send response
   else:
         # Get all users from the database
         # Send response

Avec Flask, vous importez dans l'objet de requête comme ceci :

from flask import request

@app.route('/users', methods=['GET', 'POST'])
def users():
    if request.method == 'POST':
         # Save the form data to the database
         # Send response
    else:
         # Get all users from the database
         # Send response

Dans l'exemple Flask, l'objet de requête ressemble, se sent et agit comme une variable globale, mais ce n'est pas le cas.

Si l'objet de requête était une variable globale, vous ne pourriez pas exécuter une application Flask multithread car les variables globales ne sont pas thread-safe.

Au lieu de cela, Flask utilise des contextes pour faire en sorte qu'un certain nombre d'objets "agissent" comme des globals uniquement pour le contexte particulier (un thread, un processus ou une coroutine) utilisé. Dans Flask, cela s'appelle un context-local .

Les paramètres locaux de contexte sont similaires mais finalement différents de l' implémentation locale des threads de Python pour stocker des données spécifiques à un thread. L'implémentation de Flask est plus générique afin de permettre aux travailleurs d'être des threads, des processus ou des coroutines.

Données stockées dans des contextes Flask

Lorsqu'une requête est reçue, Flask fournit deux contextes :

Le contexteLa descriptionObjets disponibles
ApplicationAssure le suivi des données au niveau de l'application (variables de configuration, enregistreur, connexion à la base de données)current_app,g
DemandeAssure le suivi des données au niveau de la demande (URL, méthode HTTP, en-têtes, données de demande, informations de session)request,session

Il convient de noter que chacun des objets ci-dessus est souvent appelé "proxies". Cela signifie simplement qu'ils sont des mandataires des saveurs globales des objets. Pour en savoir plus, consultez le deuxième article de cette série.

Flask gère la création de ces contextes lorsqu'une requête est reçue. Ils peuvent prêter à confusion car vous n'avez pas toujours accès à un objet particulier en fonction de l'état dans lequel se trouve votre application.

Regardons quelques exemples.

Exemple de contexte d'application

Supposons que vous ayez l'application Flask suivante :

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Welcome!'

if __name__ == '__main__':
    app.run()

Voyons d'abord comment utiliser l' objet current_app pour accéder au contexte Application.

Dans le shell Python, si vous essayez d'accéder à l' current_app.configobjet en dehors d'une fonction d'affichage, vous devriez voir l'erreur suivante :

$ python
>>> from flask import current_app
>>> current_app.config

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "werkzeug/local.py", line 347, in __getattr__
    return getattr(self._get_current_object(), name)
  File "werkzeug/local.py", line 306, in _get_current_object
    return self.__local()
  File "flask/globals.py", line 52, in _find_app
    raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().  See the
documentation for more information.

Pour accéder aux objets exposés par les contextes Application et Requête en dehors d'une fonction d'affichage, vous devez d'abord créer le contexte approprié :

# without a context manager
$ python

>>> from app import app
>>> from flask import current_app
>>>
>>> app_ctx = app.app_context()
>>> app_ctx.push()
>>>
>>> current_app.config["ENV"]
'production'
>>> app_ctx.pop()
>>>
# with a context manager
$ python

>>> from app import app
>>> from flask import current_app
>>>
>>> with app.app_context():
...     current_app.config["ENV"]
...
'production'
>>>

Exemple de contexte de demande

Vous pouvez utiliser la méthode test_request_context pour créer un contexte de requête :

# without a context manager
$ python

>>> from app import app
>>> from flask import request
>>>
>>> request_ctx = app.test_request_context()
>>> request_ctx.push()
>>>
>>> request.method
'GET'
>>>
>>> request.path
'/'
>>>
>>> request_ctx.pop()
>>>
# with a context manager
$ python

>>> from app import app
>>> from flask import request
>>>
>>> with app.test_request_context('/'):
...     request.method
...     request.path
...
'GET'
'/'
>>>

test_request_contextest généralement utilisé pendant les tests lorsque vous souhaitez utiliser des données de requête sans la surcharge d'une requête complète.

Exemple de test

Le moment le plus courant pour rencontrer des problèmes avec le contexte de l'application et de la demande est lorsque votre application est en cours de test :

import pytest
from flask import current_app

from app import app


@pytest.fixture
def client():
    with app.test_client() as client:
        assert current_app.config["ENV"] == "production"  # Error!
        yield client


def test_index_page(client):
   response = client.get('/')

   assert response.status_code == 200
   assert b'Welcome!' in response.data

Une fois exécutés, les tests échoueront dans le projecteur :

$ pytest
________________________ ERROR at setup of test_index_page _____________________

@pytest.fixture
def client():
    with app.test_client() as client:
>       assert current_app.config["ENV"] == "production"
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def _find_app():
        top = _app_ctx_stack.top
        if top is None:
>           raise RuntimeError(_app_ctx_err_msg)
E           RuntimeError: Working outside of application context.
E
E           This typically means that you attempted to use functionality that needed
E           to interface with the current application object in some way. To solve
E           this, set up an application context with app.app_context().  See the
E           documentation for more information.
================================= 1 error in 0.13s =================================

Pour corriger, créez un contexte d'application avant d'accéder current_app:

import pytest
from flask import current_app

from app import app


@pytest.fixture
def client():
    with app.test_client() as client:
        with app.app_context():  # New!!
            assert current_app.config["ENV"] == "production"
        yield client


def test_index_page(client):
   response = client.get('/')

   assert response.status_code == 200
   assert b'Welcome!' in response.data

Sommaire

Pour résumer, utilisez les objets suivants dans les fonctions d'affichage, les commandes CLI et les fonctions de test :

ObjetLe contexteErreur communeLa solution
current_appContexte d'applicationTravailler en dehors du contexte de l'applicationwith app.app_context():
gContexte d'applicationTravailler en dehors du contexte de l'applicationwith app.test_request_context('/'):
requestContexte de la demandeTravailler en dehors du contexte de la demandewith app.test_request_context('/'):
sessionContexte de la demandeTravailler en dehors du contexte de la demandewith app.test_request_context('/'):

Les méthodes suivantes doivent être utilisées lors des tests :

Méthode du flaconLa description
test_clientClient de test pour l'application Flask
test_request_contextPousser le contexte de la demande pour les tests

Source :  https://testdrive.io

#flask 

Top On-Demand App Development Company in USA

Looking for a top on-demand app development company in USA for your app development project?

AppClues Infotech is one of the most trusted and exceptional on-demand app development company in USA that has the greatest expertise in developing mobile apps in different industries. We have a dedicated on-demand app designer and programmer team that will help to create a perfect, user-friendly and secure mobile app for your business needs.

Why Choose Us for On-Demand Mobile App Development?
• Dedicated on-demand app developers
• A to Z on-demand app solutions
• Free Consultation
• High Experience in developing an on-demand app
• Expertise across different domains
• Flexible hiring models
• Quality Assurance
• Total technical support

For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910

#on-demand app development company #hire on-demand mobile app developers #top on-demand app developers in usa #on-demand app development solution #on-demand app development solution #top on-demand app development company in usa

Hire On-Demand Mobile App Development Company in USA

Looking to hire an On-Demand mobile app Development Company in USA for your specific app development need? We at AppClues Infotech one of the leading app development company in USA that provides a wide range of On-Demand app development solutions that match your business requirements.

For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910

#on-demand app development #hire on-demand mobile app development company in usa #hire on-demand app developers in usa #top on-demand app development company #best on-demand app development services #on-demand app development cost

On-Demand App Development Services Solution in USA

Looking for on-demand app development solutions for your business? At AppClues Infotech, we provide a wide range of on-demand services using the most advanced technology and proficiency of our team of expert on-demand app developers.

Send us your project requirement to get the exact cost of developing an on-demand app.

For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910

#on-demand app development services #hire on-demand mobile app developers #on-demand mobile app solution #on-demand app development company in usa #top on-demand app development service #best on-demand app development agency