Search Results for 'with statement'

1 POSTS

  1. 2006.10.06 Python 2.5 With Statement

Python 2.5 With Statement

Posted 2006. 10. 6. 20:18
어제 밤에 중국 마이크로소프트 리서치에 있는 후배와 엠에센으로 놀다가 새로 나온 파이썬 2.5(What's New in Python 2.5)의 특징에 대한 이야기를 하였다. 각자 주요하게 봤던 내용 중에 하나씩 이야기 했는데 나는 ctypes 패키지를 꼽았고, 후배는 with 문을 꼽았다. 이 글에서는 PEP 343에서 논의를 걸쳐 파이썬 2.5에 포함된 'with' 문을 살펴보려 한다.

with 문은 자원 관리를 용이하게 하기 위한 syntactic sugar로 다음과 같은 형태를 가진다.

with open('/etc/passwd', 'r') as f:
    for line in f:
        print line
        ... more processing code ...

위 예제는 /etc/passwd 파일을 읽기 모드(r)로 연 후에 f라는 파일 디스크립토로 처리한다. with 블록이 끝나면 자동으로 파일을 닫아준다.

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

마찬가지로 위 예제는 Lock을 잡고 Critical Section을 처리한 후에 with 블록을 벗어나면 자동으로 락을 해제해준다. 즉 일반적으로 try/finally 구문에서 처리하던 것을 with 블록을 통해 좀 더 편리하게 하자는 것이다.

구현 원리는 생각보다 간단하다. with에 사용되는 객체는 파이썬 용어에 따르면 컨텍스트 매니저(Context Manager)를 구현해야 하는데, __enter__와 __exit__ 메쏘드를 가지면 된다. 컨텍스트 매니저 객체를 with 문에 사용해주면 with 블록에 들어갈 때 __enter__가 불리고, 빠져나올 때 __exit__가 불린다. finally와 마찬가지로 예외(exception)가 발생해도 __exit__가 불리는 것이 보장된다. 컨텍스트 매니저 구현의 편의를 위해서 contextlib 모듈도 추가 되었다.

사실 with 문은 파이썬이 처음으로 도입한 것은 아니고, C#에서는 using이라는 construct로 이미 사용되고 있었다. 내가 알기로 C#도 처음은 아닌 것 같고, 다른 고전적인 언어에서 이미 사용이 되어왔던 걸로 안다. (어떤 언어인지 확실히 기억은 안 나지만...)

try/finally 구문의 불편함을 생각해 봤을 때 편리한 기능인 것만은 분명한 것 같다.


PS: ETH Zürich에서 만든 "The Oberon Programming Language"도 With 문을 제공하는데, 파이썬과 의미가 다르다. Oberon2 Language Report를 읽어보면, With문은 일종의 Type Guard 역할을 한다.

If v is a variable parameter of record type or a pointer type, and if it is of static type T0, the statement

WITH v:T1 DO s1 | v:T2 DO s2 ELSE s3 END

has the following meaning: if the dynamic type of v is T1, then the statement sequence S1 is executed where v is regarded as if it had the static type T1; else if the dynamic type of v is T2, then S2 is executed where V is regarded as if it had the static type T2; else S3 is executed. T1 and T2 must be extensions of T0. If no type test is satisfied and if an else clause is missing the program is aborted.

Example
  WITH t:CenterTree DO i := t.width; c := t.subnode END