Что такое питон «с», предназначенный для?

Я впервые встретил Python with заявлением. Я несколько лет использовал Python и даже не знал о его существовании! Учитывая его несколько неясный статус, я подумал, что стоит спросить:

  1. Что такое Python with заявлением, предназначенным для использования?
  2. Для чего ты это используешь?
  3. Есть ли какие-либо проблемы, о которых я должен знать, или общие анти-шаблоны, связанные с его использованием? В любых случаях, когда лучше использовать try..finally чем with ?
  4. Почему он не используется более широко?
  5. Какие стандартные классы библиотек совместимы с ним?

  • Множественные переменные в Python 'with' statement
  • линейная обработка файлов, for-loop vs with
  • В Python, если я вернусь внутри блока «с», будет ли файл закрыт?
  • python: создать блок «с» для нескольких менеджеров контекста
  • Исключение исключения в менеджере контекста __enter __ ()
  • Использование инструкции «с» для файлов CSV в Python
  • Поиск функций, определенных в a с помощью: Block
  • Ошибка многопроцессорной обработки Python Lib (AttributeError: __exit__)
  • 9 Solutions collect form web for “Что такое питон «с», предназначенный для?”

    1. Я считаю, что на это уже были ответы другие пользователи передо мной, поэтому я только добавляю их для полноты: инструкция с упрощает обработку исключений путем инкапсуляции общих задач подготовки и очистки в так называемых менеджерах контекста . Более подробную информацию можно найти в PEP 343 . Например, open оператор сам по себе является менеджером контекста, который позволяет открывать файл, держать его открытым, пока выполнение выполняется в контексте оператора with где вы его использовали, и закрывайте его, как только вы покидаете контекст, независимо от того, оставил ли он его из-за исключения или при регулярном потоке управления. Таким образом, оператор WITH можно использовать способами, аналогичными шаблону RAII в C ++: некоторый ресурс приобретается оператором with и освобождается при выходе из контекста.

    2. Некоторые примеры: открытие файлов с использованием with open(filename) as fp: получение блокировок с использованием with lock: (где lock является экземпляром threading.Lock ). Вы также можете contextmanager свои собственные контекстные менеджеры, используя декоратор contextlib из contextlib . Например, я часто использую это, когда мне нужно временно изменить текущий каталог, а затем вернуться туда, где я был:

       from contextlib import contextmanager import os @contextmanager def working_directory(path): current_dir = os.getcwd() os.chdir(path) try: yield finally: os.chdir(current_dir) with working_directory("data/stuff"): # do something within data/stuff # here I am back again in the original working directory 

      Вот еще один пример, который временно перенаправляет sys.stdin , sys.stdout и sys.stderr на другой дескриптор файла и восстанавливает их позже:

       from contextlib import contextmanager import sys @contextmanager def redirected(**kwds): stream_names = ["stdin", "stdout", "stderr"] old_streams = {} try: for sname in stream_names: stream = kwds.get(sname, None) if stream is not None and stream != getattr(sys, sname): old_streams[sname] = getattr(sys, sname) setattr(sys, sname, stream) yield finally: for sname, stream in old_streams.iteritems(): setattr(sys, sname, stream) with redirected(stdout=open("/tmp/log.txt", "w")): # these print statements will go to /tmp/log.txt print "Test entry 1" print "Test entry 2" # back to the normal stdout print "Back to normal stdout again" 

      И, наконец, еще один пример, который создает временную папку и очищает ее при выходе из контекста:

       from tempfile import mkdtemp from shutil import rmtree @contextmanager def temporary_dir(*args, **kwds): name = mkdtemp(*args, **kwds) try: yield name finally: shutil.rmtree(name) with temporary_dir() as dirname: # do whatever you want 

    Я бы предложил две интересные лекции:

    • PEP 343 Заявление «с»
    • Effbot Понимание инструкции Python "with"

    1. Оператор with используется для обертывания выполнения блока методами, определенными менеджером контекста. Это позволяет использовать обычную try...except...finally шаблоны использования, которые должны быть инкапсулированы для удобного повторного использования.

    2. Вы можете сделать что-то вроде:

     with open("foo.txt") as foo_file: data = foo_file.read() 

    ИЛИ

     from contextlib import nested with nested(A(), B(), C()) as (X, Y, Z): do_something() 

    ИЛИ (Python 3.1)

     with open('data') as input_file, open('result', 'w') as output_file: for line in input_file: output_file.write(parse(line)) 

    ИЛИ

     lock = threading.Lock() with lock: # Critical section of code 

    3. Я здесь не вижу Антипаттерна.
    Цитирование погружения в Python :

    try..finally хорошо. с лучше.

    4. Я предполагаю, что это связано с привычкой программистов использовать try..catch..finally заявление с других языков.

    Оператор Python with встроенной поддержкой языка Resource Acquisition Is Initialization идиома, обычно используемая в C ++. Он предназначен для безопасного сбора и освобождения ресурсов операционной системы.

    Оператор WITH создает ресурсы в пределах области / блока. Вы пишете свой код, используя ресурсы внутри блока. Когда блок выходит из ресурсов, они очищаются бесплатно независимо от результата кода в блоке (то есть, существует ли блок в обычном режиме или из-за исключения).

    Многие ресурсы в библиотеке Python, которые подчиняются протоколу, требуемому оператором with и поэтому могут использоваться с ним из коробки. Однако каждый может создавать ресурсы, которые могут использоваться в заявлении с помощью хорошо документированного протокола: PEP 0343

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

    Примером антипаттерна может быть использование внутри внутри цикла, когда было бы более эффективно иметь with внешним контуром

    например

     for row in lines: with open("outfile","a") as f: f.write(row) 

    против

     with open("outfile","a") as f: for row in lines: f.write(row) 

    Первый способ – открытие и закрытие файла для каждой row что может вызвать проблемы с производительностью по сравнению со вторым способом при открытии и закрытии файла только один раз.

    Снова для полноты я добавлю свой самый полезный вариант использования для операторов.

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

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

     from decimal import localcontext with localcontext() as ctx: ctx.prec = 42 # Perform a high precision calculation s = calculate_something() s = +s # Round the final result back to the default precision 

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

    См. PEP 343 – Оператор «с» , в конце есть примерный раздел.

    … новый оператор «с» на язык Python, чтобы можно было исключить стандартные применения операторов try / finally.

    Оператор with работает с так называемыми менеджерами контекста:

    http://docs.python.org/release/2.5.2/lib/typecontextmanager.html

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

    точки 1, 2 и 3 достаточно хорошо покрыты:

    4: он относительно новый, доступный только в python2.6 + (или python2.5 с использованием from __future__ import with_statement )

    Еще один пример поддержки «из коробки» и тот, который сначала может быть немного озадачен, когда вы привыкли к тому, как работают встроенные функции open() , являются объектами connection популярных модулей базы данных, такими как:

    • sqlite3
    • psycopg2
    • cx_Oracle

    Объектами connection являются диспетчеры контекста и, как таковые, могут быть использованы из-в-коробке в with-statement , однако при использовании вышеуказанного примечания:

    Когда with-block завершен, либо с исключением, либо без него, соединение не закрывается . В случае, если сблокируется с исключением, транзакция откатывается, в противном случае транзакция совершается.

    Это означает, что программист должен позаботиться о том, чтобы закрыть соединение самостоятельно, но позволяет приобретать соединение и использовать его в нескольких with-statements , как показано в документах psycopg2 :

     conn = psycopg2.connect(DSN) with conn: with conn.cursor() as curs: curs.execute(SQL1) with conn: with conn.cursor() as curs: curs.execute(SQL2) conn.close() 

    В приведенном выше примере вы заметите, что объекты cursor psycopg2 также являются менеджерами контекста. Из соответствующей документации о поведении:

    Когда cursor выходит из закрытого with-block он закрывается, освобождая любой связанный с ним ресурс. Состояние транзакции не изменяется.

    Python - лучший язык программирования в мире.