with
Сегодня я впервые столкнулся с заявлением Python . Я слегка использовал Python в течение нескольких месяцев и даже не знал о его существовании! Учитывая его немного неясный статус, я подумал, что стоит спросить:
- Для чего
with
предназначен оператор Python ? - Для чего ты это используешь?
- Есть ли какие-то ошибки, о которых мне нужно знать, или общие анти-паттерны, связанные с их использованием? Какие-нибудь случаи, когда это лучше,
try..finally
чем использоватьwith
? - Почему это не используется более широко?
- Какие классы стандартной библиотеки совместимы с ним?
with
в документации по Python 3.Ответы:
Я считаю, что на это уже отвечали другие пользователи до меня, поэтому я добавляю его только для полноты картины: это
with
утверждение упрощает обработку исключений, инкапсулируя общие задачи подготовки и очистки в так называемых контекстных менеджерах . Более подробную информацию можно найти в PEP 343 . Например,open
оператор сам по себе является менеджером контекста, который позволяет открывать файл, сохранять его открытым, пока выполнение находится в контекстеwith
оператора, в котором вы его использовали, и закрывать его, как только вы выходите из контекста, не важно, оставили ли вы его из-за исключения или во время регулярного потока управления. Таким образом,with
оператор может использоваться способами, подобными шаблону RAII в C ++: некоторый ресурс получаетсяwith
заявление и выпущен, когда вы выходите изwith
контекста.Вот некоторые примеры: открытие файлов с использованием
with open(filename) as fp:
, получение блокировок с использованиемwith lock:
(гдеlock
это экземплярthreading.Lock
). Вы также можете создавать свои собственные контекстные менеджеры, используяcontextmanager
декоратор изcontextlib
. Например, я часто использую это, когда мне нужно временно изменить текущий каталог, а затем вернуться туда, где я был:Вот еще один пример , который временно перенаправляет
sys.stdin
,sys.stdout
иsys.stderr
в какой - то другой дескрипторе файла и восстанавливают их позже:И, наконец, еще один пример, который создает временную папку и очищает ее при выходе из контекста:
источник
with
оператор предназначен для заполнения переменной данными до тех пор, пока не будут выполнены все инструкции под ней, а затем освободить переменную?with open('myScript.py', 'r') as f: pass
, Я ожидал , чтобы быть в состоянии назвать переменную ,f
чтобы увидеть содержание текста документа, так как это то , что будет отображаться , если документ был назначенf
через обычныйopen
заявление:f = open('myScript.py').read()
. Но вместо этого я получил следующее:<_io.TextIOWrapper name='myScript.py' mode='r' encoding='cp1252'>
. Что это значит?with
не устраняет необходимостьread
в реальном файле. Наwith
звонкиopen
- он не знает , что вам нужно сделать с ним - вы можете сделать искать, например.with
Оператор может заполнять переменную данными или вносить какие-либо другие изменения в среду до тех пор, пока не будут выполнены соответствующие инструкции, а затем выполнить любую необходимую очистку. Виды очистки, которые могут быть выполнены, такие как закрытие открытого файла, или, как это делает @Tamas в этом примере, изменение каталогов туда, где вы были раньше, и т. Д. Поскольку в Python есть сборка мусора, освобождение переменной не является важным вариант использования.with
обычно используется для других видов очистки.Я бы предложил две интересные лекции:
1. Оператор
with
используется, чтобы обернуть выполнение блока методами, определенными менеджером контекста. Это позволяетtry...except...finally
инкапсулировать общие шаблоны использования для удобного повторного использования.2. Вы можете сделать что-то вроде:
ИЛИ
ИЛИ (Python 3.1)
ИЛИ
3. Я не вижу здесь никакого Антипаттерна.
Цитируем погружение в Python :
4. Я думаю, это связано с привычкой программистов использовать
try..catch..finally
операторы из других языков.источник
with
.Оператор Python
with
является встроенной языковой поддержкойResource Acquisition Is Initialization
идиомы, обычно используемой в C ++. Он предназначен для безопасного сбора и выпуска ресурсов операционной системы.with
Оператор создает ресурсы в пределах области / блока. Вы пишете свой код, используя ресурсы внутри блока. Когда блок выходит из системы, ресурсы освобождаются полностью, независимо от результата кода в блоке (то есть, нормально ли выходит блок или из-за исключения).Многие ресурсы в библиотеке Python, которые подчиняются протоколу, требуемому
with
оператором, и поэтому могут использоваться с ним «из коробки». Однако любой может создать ресурсы, которые можно использовать в операторе with, с помощью хорошо документированного протокола: PEP 0343Используйте его всякий раз, когда вы получаете ресурсы в вашем приложении, которые должны быть явно освобождены, такие как файлы, сетевые подключения, блокировки и тому подобное.
источник
Опять же, для полноты, я добавлю мой самый полезный вариант использования для
with
заявлений.Я много занимаюсь научными вычислениями, и для некоторых задач мне нужна
Decimal
библиотека для вычислений произвольной точности. Некоторая часть моего кода мне нужна высокая точность, а для большинства других частей мне нужна меньшая точность.Я устанавливаю точность по умолчанию для небольшого числа, а затем использую,
with
чтобы получить более точный ответ для некоторых разделов:Я часто использую это с гипергеометрическим тестом, который требует деления больших чисел, получающихся в виде факториалов. Когда вы выполняете вычисления в геномном масштабе, вы должны быть осторожны с ошибками округления и переполнения.
источник
Примером антипаттерна может быть использование
with
внутри цикла, когда было бы более эффективно иметьwith
внешний циклнапример
против
Первый способ - это открытие и закрытие файла для каждого,
row
что может вызвать проблемы с производительностью по сравнению со вторым способом с открытием и закрытием файла только один раз.источник
См. PEP 343. - Оператор «with» , в конце приведен пример раздела.
источник
пункты 1, 2 и 3 достаточно хорошо освещены:
4: он относительно новый, доступен только в python2.6 + (или используя python2.5
from __future__ import with_statement
)источник
Оператор with работает с так называемыми контекстными менеджерами:
http://docs.python.org/release/2.5.2/lib/typecontextmanager.html
Идея состоит в том, чтобы упростить обработку исключений, выполнив необходимую очистку после выхода из блока with. Некоторые из встроенных в Python уже работают как контекстные менеджеры.
источник
Другим примером встроенной поддержки, который поначалу может показаться немного странным, когда вы привыкли к встроенному
open()
поведению, являютсяconnection
объекты популярных модулей базы данных, таких как:Эти
connection
объекты являются менеджерами контекста и как таковые могут быть использованы вне коробки вwith-statement
, однако при использовании указанной выше сведению , что:Это означает, что программист должен сам позаботиться о том, чтобы закрыть соединение, но позволяет установить соединение и использовать его несколько раз
with-statements
, как показано в документах psycopg2 :В приведенном выше примере вы заметите, что
cursor
объектыpsycopg2
также являются контекстными менеджерами. Из соответствующей документации по поведению:источник
В Python обычно оператор « with » используется для открытия файла, обработки данных, присутствующих в файле, а также для закрытия файла без вызова метода close (). Оператор with упрощает обработку исключений, предоставляя операции очистки.
Общая форма с:
примечание: нет необходимости закрывать файл, вызывая close () для file-var.close ()
источник