На днях я узнал две вещи о контекстных менеджерах. Первым является то, что переменная, созданная при использовании с ... как x
существуют вне контекста. Это не удивительно, я просто никогда не пробовал это раньше. Во -вторых, то, что происходит при вызове метода на диспетчете контекста за пределами с
-Поджнение, действительно зависит от реализации. Что по какой -то причине удивило меня намного больше, чем это должно. В любом случае, давайте пойдем в то, как я наткнулся на это.
Итак, на работе я наткнулся на какой -то код, который я был удивлен, работал вообще. Это связано с использованием Flask.testing. FlaskClient
Как менеджер контекста, который показан в учебном пособии: https://flask.palletsprojects.com/en/1.1.x/testing/ Анкет Я не могу поделиться кодом Но я воссоздаю сценарий с минимальным примером.
Для начала у меня есть пример приложения Flask my_flask_app.py , который содержит код:
from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "Hello World!"
Я также создал файл test_app.py , который я буду использовать для небольшого теста для приложения. Файл выглядит так:
import pytest import my_flask_app def test_helloworld(): with my_flask_app.app.test_client() as client: pass resp = client.get("/") assert resp.get_data(as_text=True) == "Hello World!"
Если вы знаете, как работают менеджеры контекста, вы, вероятно, можете увидеть проблему. Я использую Клиент
Контекстная переменная вне контекста. Я использую Пасс
Заявление здесь, но на самом деле это был еще какой -то код настройки. Это была легкая ошибка, имея неправильный уровень отступления на одной строке кода. Что было так удивительно, так это то, что тест на самом деле работает.
Это заставило меня копаться, и я наткнулся на этот вопрос Stackoverflow: https://stackoverflow.com/questions/52028124/why-use-flasks-app-test-client-over-requests-session-for-testing Анкет Итак, здесь происходит то, что менеджер контекста дает вам доступ к Stack-Stack в контексте, но это не влияет на фактическое общение. Поэтому, когда вы выходите из контекста, клиент по -прежнему работал, как и ожидалось, для того, что нам нужно в тесте.
Я мог бы противопоставить это с наиболее распространенным менеджером контекста, файл возвращался из открытым
. Итак, что мы обычно делаем, так это:
with open("my_file.txt", "r") as f: f.read()
Если бы мы сделали чтение вне блока контекста, как это:
with open("my_file.txt", "r") as f: pass f.read()
Тогда мы получаем ValueError: операция ввода/вывода в закрытом файле.
, что ожидается как идея этого контекстного диспетчера, заключается в автоматическом закрытии файла после завершения.
Подводя итог, что я беру с собой из этого открытия. Вместо слепого использования диспетчера контекста, постарайтесь понять, какой контекст он на самом деле устанавливает. Кроме того, я думаю, что это может быть уроком, когда вы разрабатываете собственных контекстных менеджеров. Убедитесь, что намерение хорошо задокументировано, и подумайте о том, как вы хотите, чтобы объект вел себя при использовании вне контекста. Возможно, будет выпущена ошибка, потому что был выпущен ресурс. В этом случае убедитесь, что сообщение об ошибке является ясным и простым для понимания.
Оригинал: “https://dev.to/fronkan/til-what-happens-when-using-the-context-manager-outside-its-with-statement-1c7c”