>  기사  >  백엔드 개발  >  Python의 with 문과 컨텍스트 관리자

Python의 with 문과 컨텍스트 관리자

高洛峰
高洛峰원래의
2017-03-01 14:15:401232검색

Python의 컨텍스트 관리자 객체로 with 문을 사용할 수 있습니다. 컨텍스트 관리자를 제공하는 contextlib 모듈을 사용하는 것은 Python 프로그래밍의 고급 기술입니다. Python. 머신러닝 요약:

0. 컨텍스트 관리자에 대하여
컨텍스트 관리자는 with 문에서 사용할 수 있는 객체이며 __enter__ 및 __exit__ 메서드를 가지고 있습니다.

with manager as var:
  do_something(var)

var = manager.__enter__()
try:
  do_something(var)
finally:
  manager.__exit__()

를 단순화한 것과 같습니다. PEP 343 정의된 컨텍스트 관리자 프로토콜을 사용하면 지루한 try...out...finally 구조를 별도의 클래스로 추상화하여 do_something 부분만 고려하도록 허용합니다.

__enter__ 메소드가 먼저 호출됩니다. var에 할당된 값을 반환할 수 있습니다. as 부분은 선택 사항입니다. 표시되지 않으면 Enter의 반환 값은 무시됩니다.
with 문 아래의 코드가 실행됩니다. try 절과 마찬가지로 성공적으로 실행되거나 중단, 계속 또는 반환되거나 예외가 발생할 수 있습니다. 두 경우 모두 블록이 끝난 후 __exit__ 메서드가 호출됩니다. 예외가 발생하면 예외 정보는 다음 섹션에서 설명하는 __exit__로 전달됩니다. 일반적으로 예외는 finally 절에서와 같이 무시될 수 있으며 __exit__가 끝난 후에 다시 발생합니다.
쓰기 작업이 완료된 후 즉시 파일이 닫히는지 확인하고 싶다고 가정해 보겠습니다.

>>> class closing(object):
...  def __init__(self, obj):
...   self.obj = obj
...  def __enter__(self):
...   return self.obj
...  def __exit__(self, *args):
...   self.obj.close()
>>> with closing(open('/tmp/file', 'w')) as f:
...  f.write('the contents\n')

여기서는 다음과 같은 작업이 완료될 때 f가 호출되는지 확인합니다. 블록이 있으면 .close()가 종료됩니다. 파일을 닫는 것은 매우 일반적인 작업이므로 이 지원은 이미 파일 클래스에 있습니다. close를 호출하고 컨텍스트 관리자 자체로 작동하는 __exit__ 메서드가 있습니다.

>>> with open('/tmp/file', 'a') as f:
...  f.write('more contents\n')

try...마지막으로 일반적인 사용법은 리소스를 해제하는 것입니다. 다양한 상황은 유사하게 구현됩니다. 리소스는 __enter__ 단계에서 획득되고 __exit__ 단계에서 해제되며, 예외가 발생하면 예외도 전달됩니다. 파일 작업과 마찬가지로 객체를 사용한 후 자연스러운 작업인 경우가 많으며 기본 지원으로 편리합니다. 각 버전마다 Python이 더 많은 곳에서 지원됩니다.

1. 컨텍스트 관리자 사용 방법:

파일 열기 및 "hello world" 작성 방법

filename="my.txt"
mode="w"
writer=open(filename,mode)
writer.write("hello world")
writer.close()

예외가 발생하면(예: 디스크가 가득 찬 경우) 5행을 실행할 기회가 없습니다. 물론, 패키징을 위해 try-finally 문 블록을 사용할 수 있습니다:

writer=open(filename,mode)
try:
  writer.write("hello world")
finally:
  writer.close()

복잡한 작업을 수행할 때 try-finally 문은 보기 흉해집니다. with 문:

with open(filename,mode) as writer:
  writer.write("hello world")

as는 open() 함수에서 반환된 콘텐츠를 참조하고 이를 새 값에 할당합니다. try-finally 작업을 완료합니다.

2. 사용자 정의 컨텍스트 관리자

with 문은 try-finally와 유사하며 컨텍스트 메커니즘을 제공합니다. with 문을 적용하려면 클래스는 두 개의 내장 함수 __enter__ 및 __exit__를 제공해야 합니다. 전자는 메인 코드가 실행되기 전에 실행되고, 후자는 메인 코드가 실행된 후에 실행됩니다. as 뒤의 변수는 __enter__ 함수에 반환됩니다.

class echo():
  def output(self):
    print "hello world"
  def __enter__(self):
    print "enter"
    return self #可以返回任何希望返回的东西
  def __exit__(self,exception_type,value,trackback):
    print "exit"
    if exception_type==ValueError:
      return True
    else:
      return Flase
 
>>>with echo as e:
  e.output()


출력:

enter
hello world
exit

__exit_ _함수 완료

def __exit__(self,exc_type,exc_value,exc_tb)

그 중, ex_type: 예외 유형; ex_value: 예외 값; ex_tb: 예외 추적 정보

When __exit__ True가 반환되고 예외가 전파되지 않습니다.

3. contextlib 모듈

contextlib 모듈의 역할은 사용하기 쉬운 컨텍스트 관리자를 제공하는 것입니다. Generator를 통해 구현됩니다. contextlib의 contextmanager는 함수 수준 컨텍스트 관리 메커니즘을 제공하는 데코레이터 역할을 합니다. 일반적으로 사용되는 프레임워크는 다음과 같습니다.

from contextlib import contextmanager
@contextmanager
def make_context():
  print 'enter'
  try:
    yield "ok"
  except RuntimeError,err:
    print 'error',err
  finally:
    print 'exit'
    
>>>with make_context() as value:
  print value


출력은 다음과 같습니다. :

  enter
  ok
  exit

그중 Yield는 예외 안전성을 보장하기 위해 try-finally로 작성됩니다(예외 처리 가능). 수익률로 반환됩니다. 항복 이전의 명령문은 코드 블록이 실행되기 전의 연산으로 간주할 수 있고, 항복 이후의 연산은 __exit__ 함수 내에서의 연산으로 간주할 수 있습니다.

스레드 잠금을 예로 들어보세요:

@contextlib.contextmanager
def loudLock():
  print 'Locking'
  lock.acquire()
  yield
  print 'Releasing'
  lock.release()
 
with loudLock():
  print 'Lock is locked: %s' % lock.locked()
  print 'Doing something that needs locking'
 
#Output:
#Locking
#Lock is locked: True
#Doing something that needs locking
#Releasing

4. contextlib.nested: 중첩 줄이기

대상:

with open(filename,mode) as reader:
  with open(filename1,mode1) as writer:
    writer.write(reader.read())

는 contextlib.nested로 단순화할 수 있습니다.

with contextlib.nested(open(filename,mode),open(filename1,mode1)) as (reader,writer):
  writer.write(reader.read())

Python 2.7 이상에서는 새로운 구문으로 대체됩니다:

with open(filename,mode) as reader,open(filename1,mode1) as writer:
  writer.write(reader.read())

5, contextlib.closing()

파일 클래스는 컨텍스트 관리자 API를 직접 지원하지만 urllib.urlopen()에서 반환된 객체와 같이 열린 핸들을 나타내는 일부 객체는 지원되지 않습니다. close() 메서드를 사용하지만 컨텍스트 관리자 API를 지원하지 않는 일부 레거시 클래스도 있습니다. 핸들이 닫혔는지 확인하려면 Closing()(클래스의 close 메서드 호출)을 사용하여 핸들에 대한 컨텍스트 관리자를 만들어야 합니다.

import contextlib
class myclass():
  def __init__(self):
    print '__init__'
  def close(self):
    print 'close()'
   
with contextlib.closing(myclass()):
  print 'ok'


출력:

__init__
ok
close()


Python의 with문과 컨텍스트 관리자에 관한 더 많은 글을 보시려면 PHP 중국어 홈페이지를 주목해주세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.