Как контексты приложений и запросов работают в Flask

В этой статье рассматривается, как контексты приложения и запроса работают в Flask.

Цели

К концу этой статьи вы должны быть в состоянии объяснить:

  1. Что такое контекст
  2. Какие данные хранятся как в контексте приложения, так и в контексте запроса
  3. Шаги, необходимые для обработки контекстов приложения и запроса, когда запрос обрабатывается в Flask
  4. Как используются прокси для контекста приложения и запроса
  5. Как использовать функции current_appи requestпрокси в представлении
  6. Что такое context-local

Что такое контекст?

Чтобы выполнить код, который вы пишете, ему нужны данные для обработки. Этими данными могут быть данные конфигурации, входные данные, данные из базы данных и так далее.

Контексты используются для отслеживания данных, которые необходимо выполнить вашему коду.

Во Flask контексты используются для предоставления необходимых данных для обработки запросов и команд интерфейса командной строки (CLI).

Хотя в этой статье основное внимание уделяется обработке запросов, представленные концепции также применимы к командам CLI.

Обработка запроса

Начнем с того, как обрабатывается запрос с высокого уровня:

Веб-сервер, сервер WSGI и схема приложения Flask

Таким образом, запрос отправляется из браузера на веб-сервер (например, Nginx или Apache) для запроса определенного URL-адреса ('/' URL-адрес на приведенной выше диаграмме). Затем веб-сервер направляет этот запрос на сервер WSGI для обработки.

WSGI, что означает интерфейс шлюза веб-сервера, представляет собой интерфейс между веб-сервером и веб-приложением на основе Python. Это необходимо, поскольку веб-сервер не может напрямую общаться с приложением Python. Для получения дополнительной информации просмотрите WSGI .

Сервер WSGI сообщает приложению Flask обработать запрос.

Приложение Flask генерирует ответ, который отправляется обратно на сервер WSGI, обратно на веб-сервер и, в конечном итоге, обратно в веб-браузер.

Эти шаги описывают цикл запрос-ответ, который является ключевой функцией обработки запроса через веб-сервер, сервер приложений WSGI и веб-приложение.

Контексты в Flask

Когда запрос получен, Flask предоставляет два контекста:

КонтекстОписаниеДоступные объекты
ЗаявлениеОтслеживает данные на уровне приложения (переменные конфигурации, регистратор, подключение к базе данных)current_app,g
ЗапросОтслеживает данные уровня запроса (URL, метод HTTP, заголовки, данные запроса, информацию о сеансе)request,session

Стоит отметить, что каждый из вышеперечисленных объектов часто называют «прокси». Это просто означает, что они являются прокси для глобальных ароматов объектов. Мы углубимся в это в ближайшее время.

Flask обрабатывает создание этих контекстов при получении запроса. Они могут вызвать путаницу, поскольку у вас не всегда есть доступ к конкретному объекту в зависимости от того, в каком состоянии находится ваше приложение.

Обзорная диаграмма

На следующей диаграмме показано, как обрабатываются контексты при обработке запроса:

Обработка запросов — Обзор

На этой диаграмме происходит много всего, поэтому мы подробно рассмотрим каждый шаг.

Шаг 1 — Веб-серверы и WSGI-серверы

Все начинается, когда веб-сервер получает запрос:

Обработка запроса — шаг 1

Работа веб-сервера заключается в маршрутизации входящих HTTP-запросов на сервер WSGI .

Apache и Nginx — два распространенных веб-сервера, а Gunicorn , uWSGI и mod_wsgi — популярные серверы WSGI.

Стоит отметить, что, хотя сервер разработки Flask является сервером WSGI, он не предназначен для использования в производстве.

Шаг 2 - Рабочий

Чтобы обработать запрос, сервер WSGI порождает рабочего для обработки запроса:

Обработка запроса — шаг 2

Рабочий процесс может быть потоком, процессом или сопрограммой. Например, рабочие будут потоками, если вы используете сервер разработки Flask с его конфигурацией по умолчанию.

Если вам интересно узнать больше о различиях между потоками, многопроцессорностью и асинхронностью в Python, ознакомьтесь со статьей « Ускорение Python с помощью параллелизма, параллелизма и асинхронности » и видео « Параллелизм в Python » .

Для этого объяснения тип работника не важен; Ключевым моментом рабочего процесса является то, что он обрабатывает один запрос за раз (отсюда необходимость в более чем одном работнике).

Шаг 3 — Контексты

Как только выполнение переключается на приложение Flask, Flask создает контексты приложения и запроса и помещает их в соответствующие стеки:

Обработка запроса — шаг 3

Для обзора в контексте приложения хранятся данные уровня приложения, такие как переменные конфигурации, подключение к базе данных и регистратор. В то же время контекст запроса хранит данные, относящиеся к запросу, которые необходимо обработать, чтобы сгенерировать ответ.

Это может показаться удивительным, но оба стека реализованы как глобальные объекты (это станет яснее в следующем разделе).

Шаг 4 - Прокси

Теперь, когда приложение Flask готово к обработке данных (в функции просмотра), а данные готовы в стеках контекста приложения и запроса, нам нужен способ соединить эти две части... прокси -серверы в помощь!

Обработка запроса — шаг 4

Прокси используются функциями представления для доступа к приложению (хранится в стеке контекста приложения) и контексту запроса (хранится в стеке контекста запроса):

  • current_app - proxy to the Application context for the worker
  • request - proxy to the Request context for the worker

At first glance, this sequence may seem confusing, as the view function appears to be accessing global objects (Application and Request context stacks) via the proxies. If this were the case, this operation would be problematic, as it's not thread-safe. You may also be thinking that these stacks (as global objects) could be accessed by any worker, which would be a security concern.

However, this design is one of the great features of Flask... the stacks are implemented as context-local objects.

For more on Proxies, review Notes On Proxies from the Flask docs and the Proxy pattern article.

Context Locals

Python has a concept of thread-local data for storing data that is specific to a thread, which is both "thread-safe and thread-unique". In other words, each thread will be able to access the data in a thread-safe manner and the data is always unique to the specific thread.

Flask implements a similar behavior (context-locals), but in a more generic way to allow for workers to be threads, processes, or coroutines.

Context-locals are actually implemented in Werkzeug, which is one of the key packages that comprises Flask. For simplicity, we'll be referencing Flask when discussing context-locals.

Когда данные хранятся в контекстно-локальном объекте, данные хранятся таким образом, что только один рабочий процесс может получить обратно. Таким образом, если два отдельных рабочих процесса получают доступ к контекстно-локальному объекту, каждый из них получит свои собственные данные, уникальные для каждого рабочего процесса.

Пример использования контекстно-локального объекта будет представлен в следующем разделе.

Подводя итог, current_appпрокси- requestсерверы и доступны в каждой функции представления, и они используются для доступа к контекстам из соответствующих стеков, которые хранятся как контекстно-локальные объекты.

Использование «стека» в контексте стеков контекста приложения и запроса делает эту концепцию еще более запутанной, чем она есть. Эти «стеки» обычно не хранят более одного контекста.

Используемая структура данных представляет собой стек, поскольку существуют очень сложные сценарии (например, внутренние перенаправления ), для которых требуется более одного элемента.

Преимущество прокси в Flask

Если бы вы создавали свою собственную веб-инфраструктуру с нуля, вы могли бы подумать о передаче контекстов приложения и запроса в каждую функцию представления, например:

@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'] })!")
       ...

На самом деле так работает ряд веб-фреймворков (включая Django ).

Тем не менее, Flask предоставляет current_appи requestпрокси, которые в конечном итоге выглядят как глобальные переменные для функции просмотра:

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'] })!")
       ...

Используя этот подход, функции просмотра не нужны контексты, передаваемые в качестве аргументов; этот подход упрощает определение функции просмотра. Однако это может вызвать путаницу, поскольку у вас не всегда есть доступ к прокси current_app-серверам и request, в зависимости от того, в каком состоянии находится ваше приложение.

НАПОМИНАНИЕ: Прокси current_appи requestна самом деле не являются глобальными переменными; они указывают на глобальные объекты, которые реализованы как локальные объекты контекста, поэтому прокси всегда уникальны для каждого рабочего процесса.

Шаг 5 - Очистка

После генерации ответа контексты запроса и приложения извлекаются из соответствующих стеков:

Обработка запроса — шаг 5

Этот шаг очищает стеки.

Затем ответ отправляется обратно в веб-браузер, который завершает обработку этого запроса.

Контекстные местные жители

Контекстно-локальные объекты реализованы с использованием локальных объектов, которые можно создать следующим образом:

$ python

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

Каждый контекст (т. е. «рабочие процессы», обсуждавшиеся в предыдущем разделе) может получить доступ к Localобъекту для хранения уникальных для контекста данных. Данные, к которым осуществляется доступ, уникальны для контекста и могут быть доступны только в этом контексте.

Объекты LocalStack аналогичны Localобъектам, но содержат стек объектов для разрешения push()и pop()операций.

В предыдущем разделе мы узнали, как используются стек контекста приложения и стек контекста запроса при обработке запроса в Flask. Эти стеки реализованы как LocalStackобъекты в глобальной памяти Flask.

Чтобы помочь укрепить работу контекстных локальных переменных, давайте рассмотрим пример, создав LocalStackобъект в глобальной памяти, а затем предоставив к нему доступ трем отдельным потокам:

Пример LocalStack с тремя потоками

Вот полный скрипт для этого примера:

"""
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!')

Этот файл создает LocalStackобъект ( thread_data_stack) для хранения данных каждого из создаваемых потоков.

thread_data_stackимитирует стек контекста приложения или стек контекста запроса в Flask.

Запускается long_running_functionв каждом из потоков:

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()

Эта функция помещает данные о потоке в thread_data_stackобъект в глобальной памяти:

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

Эта операция имитирует помещение контекста приложения или запроса в соответствующий стек.

После завершения time.sleep()функции thread_data_stackосуществляется доступ к данным из:

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

Эта операция имитирует использование прокси app_context-серверов и request, поскольку эти прокси-серверы получают доступ к данным на вершине своего соответствующего стека.

В конце функции данные извлекаются из thread_data_stack:

thread_data_stack.pop()

Эта операция имитирует извлечение контекста приложения или запроса из соответствующего стека.

Когда скрипт запускается, он запускает 3 потока:

# 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()

И joinкаждый поток, поэтому скрипт ждет, пока каждый поток не завершит выполнение:

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

Давайте запустим этот скрипт, чтобы посмотреть, что произойдет:

$ 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!

Что действительно интересно в каждом потоке, так это то, что все они указывают на один и тот же LocalStackобъект в памяти:

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>

Когда каждый поток обращается к thread_data_stack, доступ уникален для этого потока! Это волшебство LocalStackLocal) — они разрешают контекстно-уникальный доступ:

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

Доступ к thread_data_stackтакже потокобезопасен, в отличие от обычного доступа к глобальной памяти.

Вывод

Одним из мощных (но запутанных) аспектов Flask является то, как обрабатываются контексты приложения и запроса. Надеюсь, эта статья внесла некоторую ясность в эту тему!

Контексты Application и Request предоставляют необходимые данные при обработке запросов или команд CLI. Обязательно используйте прокси current_appи requestдля доступа к контексту приложения и контексту запроса.

Источник:  https://testdriven.io

#python #flask 

What is GEEK

Buddha Community

Как контексты приложений и запросов работают в Flask

Как контексты приложений и запросов работают в Flask

В этой статье рассматривается, как контексты приложения и запроса работают в Flask.

Цели

К концу этой статьи вы должны быть в состоянии объяснить:

  1. Что такое контекст
  2. Какие данные хранятся как в контексте приложения, так и в контексте запроса
  3. Шаги, необходимые для обработки контекстов приложения и запроса, когда запрос обрабатывается в Flask
  4. Как используются прокси для контекста приложения и запроса
  5. Как использовать функции current_appи requestпрокси в представлении
  6. Что такое context-local

Что такое контекст?

Чтобы выполнить код, который вы пишете, ему нужны данные для обработки. Этими данными могут быть данные конфигурации, входные данные, данные из базы данных и так далее.

Контексты используются для отслеживания данных, которые необходимо выполнить вашему коду.

Во Flask контексты используются для предоставления необходимых данных для обработки запросов и команд интерфейса командной строки (CLI).

Хотя в этой статье основное внимание уделяется обработке запросов, представленные концепции также применимы к командам CLI.

Обработка запроса

Начнем с того, как обрабатывается запрос с высокого уровня:

Веб-сервер, сервер WSGI и схема приложения Flask

Таким образом, запрос отправляется из браузера на веб-сервер (например, Nginx или Apache) для запроса определенного URL-адреса ('/' URL-адрес на приведенной выше диаграмме). Затем веб-сервер направляет этот запрос на сервер WSGI для обработки.

WSGI, что означает интерфейс шлюза веб-сервера, представляет собой интерфейс между веб-сервером и веб-приложением на основе Python. Это необходимо, поскольку веб-сервер не может напрямую общаться с приложением Python. Для получения дополнительной информации просмотрите WSGI .

Сервер WSGI сообщает приложению Flask обработать запрос.

Приложение Flask генерирует ответ, который отправляется обратно на сервер WSGI, обратно на веб-сервер и, в конечном итоге, обратно в веб-браузер.

Эти шаги описывают цикл запрос-ответ, который является ключевой функцией обработки запроса через веб-сервер, сервер приложений WSGI и веб-приложение.

Контексты в Flask

Когда запрос получен, Flask предоставляет два контекста:

КонтекстОписаниеДоступные объекты
ЗаявлениеОтслеживает данные на уровне приложения (переменные конфигурации, регистратор, подключение к базе данных)current_app,g
ЗапросОтслеживает данные уровня запроса (URL, метод HTTP, заголовки, данные запроса, информацию о сеансе)request,session

Стоит отметить, что каждый из вышеперечисленных объектов часто называют «прокси». Это просто означает, что они являются прокси для глобальных ароматов объектов. Мы углубимся в это в ближайшее время.

Flask обрабатывает создание этих контекстов при получении запроса. Они могут вызвать путаницу, поскольку у вас не всегда есть доступ к конкретному объекту в зависимости от того, в каком состоянии находится ваше приложение.

Обзорная диаграмма

На следующей диаграмме показано, как обрабатываются контексты при обработке запроса:

Обработка запросов — Обзор

На этой диаграмме происходит много всего, поэтому мы подробно рассмотрим каждый шаг.

Шаг 1 — Веб-серверы и WSGI-серверы

Все начинается, когда веб-сервер получает запрос:

Обработка запроса — шаг 1

Работа веб-сервера заключается в маршрутизации входящих HTTP-запросов на сервер WSGI .

Apache и Nginx — два распространенных веб-сервера, а Gunicorn , uWSGI и mod_wsgi — популярные серверы WSGI.

Стоит отметить, что, хотя сервер разработки Flask является сервером WSGI, он не предназначен для использования в производстве.

Шаг 2 - Рабочий

Чтобы обработать запрос, сервер WSGI порождает рабочего для обработки запроса:

Обработка запроса — шаг 2

Рабочий процесс может быть потоком, процессом или сопрограммой. Например, рабочие будут потоками, если вы используете сервер разработки Flask с его конфигурацией по умолчанию.

Если вам интересно узнать больше о различиях между потоками, многопроцессорностью и асинхронностью в Python, ознакомьтесь со статьей « Ускорение Python с помощью параллелизма, параллелизма и асинхронности » и видео « Параллелизм в Python » .

Для этого объяснения тип работника не важен; Ключевым моментом рабочего процесса является то, что он обрабатывает один запрос за раз (отсюда необходимость в более чем одном работнике).

Шаг 3 — Контексты

Как только выполнение переключается на приложение Flask, Flask создает контексты приложения и запроса и помещает их в соответствующие стеки:

Обработка запроса — шаг 3

Для обзора в контексте приложения хранятся данные уровня приложения, такие как переменные конфигурации, подключение к базе данных и регистратор. В то же время контекст запроса хранит данные, относящиеся к запросу, которые необходимо обработать, чтобы сгенерировать ответ.

Это может показаться удивительным, но оба стека реализованы как глобальные объекты (это станет яснее в следующем разделе).

Шаг 4 - Прокси

Теперь, когда приложение Flask готово к обработке данных (в функции просмотра), а данные готовы в стеках контекста приложения и запроса, нам нужен способ соединить эти две части... прокси -серверы в помощь!

Обработка запроса — шаг 4

Прокси используются функциями представления для доступа к приложению (хранится в стеке контекста приложения) и контексту запроса (хранится в стеке контекста запроса):

  • current_app - proxy to the Application context for the worker
  • request - proxy to the Request context for the worker

At first glance, this sequence may seem confusing, as the view function appears to be accessing global objects (Application and Request context stacks) via the proxies. If this were the case, this operation would be problematic, as it's not thread-safe. You may also be thinking that these stacks (as global objects) could be accessed by any worker, which would be a security concern.

However, this design is one of the great features of Flask... the stacks are implemented as context-local objects.

For more on Proxies, review Notes On Proxies from the Flask docs and the Proxy pattern article.

Context Locals

Python has a concept of thread-local data for storing data that is specific to a thread, which is both "thread-safe and thread-unique". In other words, each thread will be able to access the data in a thread-safe manner and the data is always unique to the specific thread.

Flask implements a similar behavior (context-locals), but in a more generic way to allow for workers to be threads, processes, or coroutines.

Context-locals are actually implemented in Werkzeug, which is one of the key packages that comprises Flask. For simplicity, we'll be referencing Flask when discussing context-locals.

Когда данные хранятся в контекстно-локальном объекте, данные хранятся таким образом, что только один рабочий процесс может получить обратно. Таким образом, если два отдельных рабочих процесса получают доступ к контекстно-локальному объекту, каждый из них получит свои собственные данные, уникальные для каждого рабочего процесса.

Пример использования контекстно-локального объекта будет представлен в следующем разделе.

Подводя итог, current_appпрокси- requestсерверы и доступны в каждой функции представления, и они используются для доступа к контекстам из соответствующих стеков, которые хранятся как контекстно-локальные объекты.

Использование «стека» в контексте стеков контекста приложения и запроса делает эту концепцию еще более запутанной, чем она есть. Эти «стеки» обычно не хранят более одного контекста.

Используемая структура данных представляет собой стек, поскольку существуют очень сложные сценарии (например, внутренние перенаправления ), для которых требуется более одного элемента.

Преимущество прокси в Flask

Если бы вы создавали свою собственную веб-инфраструктуру с нуля, вы могли бы подумать о передаче контекстов приложения и запроса в каждую функцию представления, например:

@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'] })!")
       ...

На самом деле так работает ряд веб-фреймворков (включая Django ).

Тем не менее, Flask предоставляет current_appи requestпрокси, которые в конечном итоге выглядят как глобальные переменные для функции просмотра:

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'] })!")
       ...

Используя этот подход, функции просмотра не нужны контексты, передаваемые в качестве аргументов; этот подход упрощает определение функции просмотра. Однако это может вызвать путаницу, поскольку у вас не всегда есть доступ к прокси current_app-серверам и request, в зависимости от того, в каком состоянии находится ваше приложение.

НАПОМИНАНИЕ: Прокси current_appи requestна самом деле не являются глобальными переменными; они указывают на глобальные объекты, которые реализованы как локальные объекты контекста, поэтому прокси всегда уникальны для каждого рабочего процесса.

Шаг 5 - Очистка

После генерации ответа контексты запроса и приложения извлекаются из соответствующих стеков:

Обработка запроса — шаг 5

Этот шаг очищает стеки.

Затем ответ отправляется обратно в веб-браузер, который завершает обработку этого запроса.

Контекстные местные жители

Контекстно-локальные объекты реализованы с использованием локальных объектов, которые можно создать следующим образом:

$ python

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

Каждый контекст (т. е. «рабочие процессы», обсуждавшиеся в предыдущем разделе) может получить доступ к Localобъекту для хранения уникальных для контекста данных. Данные, к которым осуществляется доступ, уникальны для контекста и могут быть доступны только в этом контексте.

Объекты LocalStack аналогичны Localобъектам, но содержат стек объектов для разрешения push()и pop()операций.

В предыдущем разделе мы узнали, как используются стек контекста приложения и стек контекста запроса при обработке запроса в Flask. Эти стеки реализованы как LocalStackобъекты в глобальной памяти Flask.

Чтобы помочь укрепить работу контекстных локальных переменных, давайте рассмотрим пример, создав LocalStackобъект в глобальной памяти, а затем предоставив к нему доступ трем отдельным потокам:

Пример LocalStack с тремя потоками

Вот полный скрипт для этого примера:

"""
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!')

Этот файл создает LocalStackобъект ( thread_data_stack) для хранения данных каждого из создаваемых потоков.

thread_data_stackимитирует стек контекста приложения или стек контекста запроса в Flask.

Запускается long_running_functionв каждом из потоков:

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()

Эта функция помещает данные о потоке в thread_data_stackобъект в глобальной памяти:

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

Эта операция имитирует помещение контекста приложения или запроса в соответствующий стек.

После завершения time.sleep()функции thread_data_stackосуществляется доступ к данным из:

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

Эта операция имитирует использование прокси app_context-серверов и request, поскольку эти прокси-серверы получают доступ к данным на вершине своего соответствующего стека.

В конце функции данные извлекаются из thread_data_stack:

thread_data_stack.pop()

Эта операция имитирует извлечение контекста приложения или запроса из соответствующего стека.

Когда скрипт запускается, он запускает 3 потока:

# 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()

И joinкаждый поток, поэтому скрипт ждет, пока каждый поток не завершит выполнение:

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

Давайте запустим этот скрипт, чтобы посмотреть, что произойдет:

$ 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!

Что действительно интересно в каждом потоке, так это то, что все они указывают на один и тот же LocalStackобъект в памяти:

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>

Когда каждый поток обращается к thread_data_stack, доступ уникален для этого потока! Это волшебство LocalStackLocal) — они разрешают контекстно-уникальный доступ:

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

Доступ к thread_data_stackтакже потокобезопасен, в отличие от обычного доступа к глобальной памяти.

Вывод

Одним из мощных (но запутанных) аспектов Flask является то, как обрабатываются контексты приложения и запроса. Надеюсь, эта статья внесла некоторую ясность в эту тему!

Контексты Application и Request предоставляют необходимые данные при обработке запросов или команд CLI. Обязательно используйте прокси current_appи requestдля доступа к контексту приложения и контексту запроса.

Источник:  https://testdriven.io

#python #flask 

joe biden

1615787193

Kонвертер MBOX в PST - Бесплатный MBOX в PST для конвертации файла MBOX в файл PST

Descargue el MBOX al convertidor PST y convierta los archivos MBOX al formato PST. Con esta aplicación, los archivos se convierten a gran velocidad sin ningún problema. Para conocer la aplicación el usuario puede instalar la versión demo de esta aplicación y así conocer la aplicación y su funcionamiento. Con una alta velocidad de compatibilidad, la aplicación convierte todos los archivos MBOX en formato PST.

Conozca el funcionamiento de la aplicación.

Esta aplicación avanzada funciona en un orden específico para convertir los archivos MBOX a formato PST. Por lo tanto, a continuación se muestran algunos de los puntos que hablan sobre la aplicación y ver si la aplicación cumple con todas las expectativas del usuario.

  • Los usuarios pueden convertir archivos MBOX a granel y sin problemas.
  • Con la ubicación especificada por el usuario, los datos se convierten rápidamente.
  • La aplicación proporciona una conversión directa.
  • De forma avanzada, se realiza el proceso de conversión.
  • La aplicación proporciona una conversión rápida con solo un clic.
  • La aplicación funciona en cualquier aplicación de Windows, incluidos XP o Vista.
  • Cualquier archivo MBOX de correo electrónico se convierte en este convertidor inteligente.
  • La aplicación guarda el archivo localmente.

Por lo tanto, la aplicación ofrece estas funciones avanzadas que permiten que el software funcione de manera avanzada.

¿Cómo convertir archivos MBOX a PST?

Los usuarios pueden convertir el archivo en unos pocos pasos sin asistencia técnica. Siga estos pasos para convertir su archivo MBOX al formato PST de Outlook:

Paso 1: descargue el convertidor MBOX a PST
Paso 2- Inicie el convertidor
Paso 3- Seleccione los archivos MBOX que desea convertir
Paso 4- Ahora, elija el tipo que desea exportar los archivos.
Paso 5- Elija la ubicación donde desea guardar el archivo
Paso 6- Finalmente, haga clic derecho en el botón “Convertir ahora”.

Estos pasos pueden ser realizados por cualquier usuario novato.

Algunos de los atributos de este convertidor inteligente

Analicemos las funciones inteligentes de este convertidor que se indican a continuación:

  1. Convierta cualquier archivo MBOX

Esta herramienta convierte archivos MBOX de cualquier tipo desde Thunderbird a Apple Mail. Este es un convertidor avanzado.

  1. Conversión masiva de archivos MBOX

Los usuarios pueden convertir cualquier cantidad de archivos de datos sin ningún obstáculo. No importa cuál sea el tamaño del archivo MBOX, la conversión procede.

  1. Solo se convierten los archivos seleccionados

Los archivos que selecciona el usuario se convierten de archivos MBOX al formato PST de Outlook. Los resultados convertidos son los deseados por los usuarios.

  1. Ubicación personalizada

El usuario puede guardar el archivo en cualquier ubicación donde el usuario quiera guardarlo. En una ubicación adecuada, se guardan los datos convertidos.

  1. Buena compatibilidad

El usuario proporciona una interfaz fácil de usar que ayuda al usuario a convertir los archivos sin problemas y sin ningún obstáculo.

  1. Excelente precisión

El resultado proporcionado por la aplicación es 100% exacto. La calidad del resultado sigue siendo impecable.

Conclusión

La aplicación da todos los resultados adecuados después de la conversión. Con una alta velocidad de compatibilidad, la tarea de conversión es procesada por la aplicación sin ningún error. Descargue la versión de demostración gratuita del convertidor MBOX a PST para ver si funciona.

Más información:- https://www.datavare.com/ru/конвертер-mbox-в-pst.html

#конвертер mbox в pst #mbox в импортер pst #преобразование mbox в pst #mbox в экспортер pst #конвертировать mbox в pst #импортировать mbox в pst

Как контексты приложения и запроса работают в Flask

Цель этого поста — прояснить, как контексты приложения и запроса работают в Flask.

Цели

К концу этого поста вы должны быть в состоянии объяснить:

  1. Как Flask обрабатывает объект запроса и чем это отличается от других веб-фреймворков
  2. Что такое приложение и контекст запроса
  3. Какие данные хранятся как в контексте приложения, так и в контексте запроса
  4. Как использовать current_app, test_request_context, и test_clientв правильном контексте

Вы также должны быть в состоянии исправить следующую ошибку:

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().

Контексты в Flask

В отличие от Django и других веб-фреймворков, функции представления Flask не принимают объект запроса, содержащий метаданные о HTTP-запросе.

Пример Джанго:

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

С Flask вы импортируете объект запроса следующим образом:

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

В примере с Flask объект запроса выглядит, ощущается и действует как глобальная переменная, но это не так.

Если бы объект запроса был глобальной переменной, вы не смогли бы запустить многопоточное приложение Flask, поскольку глобальные переменные не являются потокобезопасными.

Вместо этого Flask использует контексты , чтобы заставить ряд объектов «действовать» как глобальные только для конкретного используемого контекста (потока, процесса или сопрограммы). Во Flask это называется context-local .

Локальные переменные контекста похожи на локальную реализацию потока в Python, но в конечном итоге отличаются от нее для хранения данных, специфичных для потока. Реализация Flask является более общей, чтобы рабочие могли быть потоками, процессами или сопрограммами.

Данные, хранящиеся в контекстах Flask

Когда запрос получен, Flask предоставляет два контекста:

КонтекстОписаниеДоступные объекты
ЗаявлениеОтслеживает данные на уровне приложения (переменные конфигурации, регистратор, подключение к базе данных)current_app,g
ЗапросОтслеживает данные уровня запроса (URL, метод HTTP, заголовки, данные запроса, информацию о сеансе)request,session

Стоит отметить, что каждый из вышеперечисленных объектов часто называют «прокси». Это просто означает, что они являются прокси для глобальных ароматов объектов. Подробнее об этом читайте во втором посте этой серии.

Flask обрабатывает создание этих контекстов при получении запроса. Они могут вызвать путаницу, поскольку у вас не всегда есть доступ к конкретному объекту в зависимости от того, в каком состоянии находится ваше приложение.

Давайте рассмотрим несколько примеров.

Пример контекста приложения

Предположим, у вас есть следующее приложение Flask:

from flask import Flask

app = Flask(__name__)

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

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

Во-первых, давайте посмотрим, как работать с объектом current_app для доступа к контексту приложения.

В оболочке Python, если вы попытаетесь получить доступ к current_app.configобъекту вне функции представления, вы должны увидеть следующую ошибку:

$ 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.

Чтобы получить доступ к объектам, предоставляемым контекстами приложения и запроса вне функции представления, вам необходимо сначала создать соответствующий контекст:

# 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'
>>>

Пример контекста запроса

Вы можете использовать метод test_request_context для создания контекста запроса:

# 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_contextобычно используется во время тестирования, когда вы хотите использовать данные запроса без накладных расходов на полный запрос.

Пример тестирования

Чаще всего проблемы с контекстом приложения и запроса возникают, когда ваше приложение находится на стадии тестирования:

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

При запуске тесты не пройдут в фикстуре:

$ 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 =================================

Чтобы исправить, создайте контекст приложения перед доступом 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

Резюме

Подводя итог, используйте следующие объекты в функциях представления, командах CLI и функциях тестирования:

ОбъектКонтекстРаспространенная ошибкаРешение
current_appКонтекст приложенияРабота вне контекста приложенияwith app.app_context():
gКонтекст приложенияРабота вне контекста приложенияwith app.test_request_context('/'):
requestКонтекст запросаРабота вне контекста запросаwith app.test_request_context('/'):
sessionКонтекст запросаРабота вне контекста запросаwith app.test_request_context('/'):

При тестировании следует использовать следующие методы:

Фляжный методОписание
test_clientТестовый клиент для приложения Flask
test_request_contextКонтекст push-запроса для тестирования

Источник:  https://testdriven.io

#flask 

Как экспортировать базу данных EML в формат PST?

Теперь пользователь может конвертировать свои файлы EML в формат PST, просто установив этот конвертер на свой компьютер. Конвертер EML в PST преобразует ваши данные с полной точностью без ущерба для данных любой ценой. Приложение надежное и простое в использовании.

Высокая скорость преобразования и 100% точность позволяют сэкономить время пользователей. Кроме того, всем пользователям доступна демонстрационная версия, которая может увидеть работу программного обеспечения.

Скачать сейчас

Зачем использовать конвертер EML в PST

Преобразование файла EML в формат PST займет много времени, если выполняется вручную, но это можно сделать с высокой скоростью с помощью конвертера EML в PST. Поэтому, прежде чем получать какие-либо дополнительные сведения, давайте сначала узнаем о конвертере EML в PST.

  • Приложение работает без сбоев в любой операционной системе Windows.
  • Приложение может конвертировать файлы массово.
  • Данные могут быть автоматически сохранены конвертером.
  • Преобразование выполняется на высокой скорости.
  • Результат, полученный после конвертации, точен на 100%.
  • Для использования приложения пользователю не нужна техническая поддержка или помощь.
  • Пользователи могут сохранить файл в любом месте по своему выбору.
  • Для проверки папок доступна бесплатная демо-версия.

Ключевой атрибут конвертера EML в PST

Конвертер EML в PST имеет множество функций, которые делают его уникальным и надежным конвертером. Поэтому ниже приведены некоторые особенности этого умного преобразователя:

1. Обеспечивает только определенное преобразование.
Приложение преобразует только определенные файлы EML в формат PST, что нормально. Конвертер поддерживает все версии Windows.

2. Поддерживает массовое преобразование.
Это умное приложение может массово конвертировать файлы EML в формат PST. Все преобразованные файлы сохраняются в одной папке PST и образуют надежный файл Outlook.

3. Преобразование здоровых данных
Приложение конвертирует только те файлы, которые не повреждены. Таким образом, результат будет 100% точным без потери данных. Таким образом, результат оправдывает ожидания пользователя.

4. Автоматическое сохранение данных.
Пользователи могут сохранять данные в любом месте или использовать параметр по умолчанию. Таким образом, пользователь может автоматически сохранять свои преобразованные данные. Таким образом, пользователю легко сохранить данные.

5. Поддерживает данные в иерархическом порядке.
Приложение поддерживает данные в иерархическом порядке, и оригинальность данных также сохраняется в течение всего процесса преобразования.

Заключительные слова

Теперь пользователи могут файлы конвертировать EML в PST с помощью этого конвертера. Приложение отлично работает в различных версиях Windows без каких-либо препятствий. Пользователи могут использовать бесплатную демо-версию перед использованием приложения.

#конвертер eml в pst #eml в pst экспортер #eml в pst импортер #импортировать eml в pst #конвертировать eml в pst

joe biden

1617084471

Бесплатный Kонвертер EML в PST - EML файл в PST для Конвертировать EML в файл PST

Попробуйте конвертер EML в Outlook PST, чтобы быстро преобразовать файлы EML в формат Outlook PST без каких-либо проблем. Приложение выполняет свою задачу преобразования надежно, без каких-либо ошибок или внесения каких-либо изменений в файлы EML, которые вы выберете для преобразования. С помощью этого приложения пользователи могут выбирать несколько файлов EML без каких-либо ошибок. Приложение обеспечивает отличный результат конвертации для своих пользователей. Он обладает высокой скоростью вычислений и бесперебойно работает в любой версии приложения Windows, пользователям не нужно использовать специальную систему для преобразования своих файлов EML в формат Outlook в этом удивительном приложении.

О конвертере EML в Outlook

Приложение представляет собой простой удобный интерфейс, который предоставляет пользователям хорошо упрощенную платформу для легкого выполнения задачи преобразования. Более того, приложение может быть привлечено к суду любыми нетехническими или техническими пользователями без каких-либо проблем из-за его дружественного пользовательского интерфейса. Приложение может конвертировать несколько файлов EML за один раз, поскольку приложение способно конвертировать файлы EML в большом количестве. Приложение также может создать файл Outlook PST большого размера, преобразовав файлы EML в группу.

Это хорошо продуманное приложение, которое подходит для любой версии Windows и поддерживает любую версию файлов Outlook. Кроме того, он переносит файлы EML в поддерживающий почтовый клиент. Для использования приложения техническая помощь не требуется. Кроме того, вы можете сохранить преобразованные данные в любом месте по вашему выбору без каких-либо обязательств. Это быстрый и хорошо поддерживаемый инструмент преобразования EML в Outlook PST, который оправдывает все ожидания пользователей.

Вы можете попробовать демо-версию приложения и попробовать конвертировать несколько файлов EML.

Привлекательные ключевые особенности приложения

Приложение состоит из ключевых атрибутов, которые используются для упрощения работы преобразования. Эти функции приведены ниже, давайте рассмотрим эти функции:

Конвертируются только файлы EML
Только файлы EML конвертируются приложением в формат Outlook PST без каких-либо препятствий. Приложение представляет собой простое и упорядоченное приложение, которое напрямую конвертирует файлы EML в формат Outlook. Независимо от размера файлов EML приложение преобразует данные в упрощенном виде.

Массовое преобразование файлов
Приложение выполняет массовое преобразование данных без каких-либо препятствий. Пользователи могут конвертировать не один или два, а множество файлов EML с помощью этого удивительного приложения без потери данных. Приложение подходит для использования и обеспечивает полную конфиденциальность ваших данных.

Желаемый результат конвертации
Приложение поддерживает выборочное преобразование файлов, поэтому пользователям предоставляется желаемый результат. В одном процессе преобразования приложение предоставляет пользователям точный и желаемый результат.

Сохранение в желаемое место
Преобразованные файлы сохраняются в том месте, которое требуется пользователям. Таким образом, приложение без проблем управляет вашими данными.

Сохранение данных вручную
Приложение поддерживает ручное сохранение данных, преобразованных приложением. Пользователи могут сохранять преобразованные файлы где угодно. Преобразованные данные могут быть сохранены в любом месте в локальной системе пользователя.

Легко организовать
Приложение систематизирует ваши данные и поддерживает их в иерархическом порядке. Для запуска приложения не требуется никакой технической помощи. Пользователи с любым опытом могут легко использовать приложение без каких-либо препятствий.

Шаги, которым необходимо следовать

Есть шаги, которые пользователь должен выполнить, чтобы выполнить свою задачу преобразования. Эти базовые шаги может выполнить любой начинающий пользователь. Давайте посмотрим на эти шаги;

Шаг 1 - Установите приложение в вашу систему Windows.
Шаг 2 - Запустите приложение
Шаг 3 - Выберите файлы EML, которые необходимо преобразовать.
Шаг 4 - Выберите режим, в котором вы хотите преобразовать файлы EML в
Шаг 5 - Теперь выберите место для сохранения преобразованных файлов EML.
Шаг 6 - Наконец, нажмите кнопку конвертировать, чтобы завершить задачу конвертации.

Это несколько основных и простых шагов, которые может выполнить любой начинающий пользователь.

Заключительное заявление

Это расширенное приложение разработано таким образом, чтобы пользователи не сталкивались с какими-либо проблемами при выполнении задачи преобразования. Приложfwение представляет собой очень упрощенное приложение.

Попробуйте демо-версию приложения, эта демо-версия доступна бесплатно любому пользователю. Хотя демо-версия позволяет конвертировать только несколько файлов. Для неограниченной конвертации пользователям необходимо купить лицензионную версию приложения.

Больше информации:- https://www.datavare.com/ru/конвертер-eml-в-pst.html

#конвертер eml в pst #конвертировать eml в pst #конвертировать живую почту windows в pst #экспортировать живую почту windows в pst #импортировать живую почту windows в pst