본문 바로가기

코딩/Python

[Python/파이썬] with ~ as ~ 구문, Magic Mathod(매직 메서드)

반응형

  파이썬을 활용하다보면 파일을 열고 수정한 후, 닫는 형태의 프로세스가 많다. 보통은 객체의 .Quit( )라던가 .Close( )와 같은 함수를 통해 직접 파일을 닫는다. 만약, 객체를 닫는 함수를 사용하지 않으면 프로그램이 종료되어도 계속 해당 객체가 열려있어 메모리를 점유하고 있게 된다. 메모리를 불필요하게 낭비하게 되는 것이다.

 

  그래서 파이썬에서는 with ~ as ~ 라는 구문을 제공한다. 개발자가 실수로 close( ) 를 하지 않아도 with ~ as ~ 구문이 끝나면 자동으로 객체를 close 하게 해준다. 다른 사람들의 코드를 보면 with ~ as ~ 라는 구문이 가끔 나오는 경우가 있어 이번 포스팅에서는 with를 사용하는 방법을 간단히 정리한다.

 

 

1. file open( ), close( )

 

 

  먼저 임의의 text파일을 작성해보았다. text 파일 내부에는 투손플레이스라는 문자열이 입력되어 있다. 파이썬 open( )함수를 통해 이 text 파일을 열고 입력된 첫줄을 읽어올 것이다.

 

 

text_data.txt

 

 

<코드>

 #text 파일이 있는 경로
path = r"C:\Users\Desktop\VS CODE"

#text 파일 열기
f = open(path+"/"+"test_data.txt", "r", encoding='utf-8') 

#첫줄 읽어오기
firstline = f.readline()

#text 파일 닫기
f.close()

#첫줄 출력하기
print(firstline)

 

 

  먼저 주의해야할 점은 open 함수 사용시 encoding = 'utf-8'을 입력하지 않으면 아래와 같이 UnicodeDecodeError 가 발생할 수 있음을 참고하자.

 

 

<결과 : Error 발생시>

Traceback (most recent call last):
  File "c:\Users\Desktop\VS CODE\Project\practice\p2.py", line 4, in <module>
    firstline = f.readline()
UnicodeDecodeError: 'cp949' codec can't decode byte 0xed in position 0: illegal multibyte sequence

 

 

  첫줄을 정상적으로 읽어오면 터미널창에 "투손플레이스"라는 문자열을 출력한다. 참고로 .readline( )이라는 함수는 텍스트파일의 첫줄을 읽어온다.

 

 

<결과 : 정상>

투손플레이스

 

 

  한가지 실험을 위해 f.close()를 firstline 변수 설정 위에 이동시켜 실행해보았다.

 

 

<코드>

path = r"C:\Users\Desktop\VS CODE"

f = open(path+"/"+"test_data.txt", "r", encoding='utf-8')
f.close()
firstline = f.readline()

 

<결과 : Error 발생>

ValueError: I/O operation on closed file.

 

 

  결과를 보면 알겠지만 f.readline( )에서 에러가 발생한다. 이유는 open 된 text 파일을 닫아버렸기 때문이다. 따라서 f.close( ) 를 하지않으면 text파일은 계속 열려있게 된다. f라는 객체가 PC의 메모리를 계속 점유하고 있는 것이다. 따라서 f라는 객체를 닫으려면 위 구문처럼 파일에 볼일이 끝나면 Close( )로 닫아주던가 본 포스팅의 주제인 with ~ as를 사용해야 한다.

 

 

 

2. with ~ as ~ 사용법

 

 

  with 구문의 사용법은 아래와 같다.

* with [expression] as [변수명]

 

1에서 다뤘던 예시를 아래와 같이 with 구문으로 표현할 수 있다.

 

 

<코드>

path = r"C:\Users\Desktop\VS CODE"

with open(path+"/"+"test_data.txt", "r", encoding='utf-8') as f:
    firstline = f.readline()
    print(firstline)

 

<결과>

투손플레이스

 

 

  만약 텍스트파일에 내용을 쓰고 싶다면 open 내부 파라미터의 "r"이 아닌 "w"로 하고 f.write( ) 를 사용하면 된다.

 

<코드>

path = r"C:\Users\Desktop\VS CODE"

with open(path+"/"+"test_data.txt", "w", encoding='utf-8') as f:
    f.write("입력테스트")

 

<결과>

 

 

 

3. with를 class에 응용하기 (파이썬의 Magic Mathod)

 

 

  위 open 함수 이외의 사용이 끝난 객체를 종료시키려면 어떤 방법을 사용해야 할까? 검색을 해보니 파이썬의 매직 메소드(Magic Mathod)라는 내용이 있다. 간단히 요약하면, with 구문의 표현식을 open 함수 이외에 사용자가 임의로 정의한 클래스 객체로 정의할 수 있다. 이 방식을 사용하려면 class 내부 메소드에 __enter__( ), __exit__(  ) 메소드에 대한 내용을 입력해야 한다. 

 

  객체가 실행될 때 __enter__( )가 자동으로 호출되며 종료될 때는 __exit__( )를 호출한다. 아래 예시를 보자.

 

 

<코드>

class Withtest:
    #초기화 메서드 정의
    def __init__(self):
        self.temp = "초기화 메서드"
    
    #객체가 호출될 때 자동으로 실행
    def __enter__(self):
        print(self.temp)
        return self # 반환값이 있어야 VARIABLE를 블록내에서 사용할 수 있다

    def printText(self):
        print("메소드 호출 테스트")
    #with 구문 통해 객체가 종료될 때 자동으로 실행
    def __exit__(self, exc_type, exc_val, exc_tb):
        #종료 구문 설정하기(세션의 종료 등)
        print('with 통해 종료')

#객체 생성 및 with 구문 실행
if __name__ == "__main__":
    withclass = Withtest()

    with withclass as wc:
        wc.printText()

 

<결과>

초기화 메서드
메소드 호출 테스트
with 통해 종료

 

 

  위 코드를 확인해보면 실행부에서 withclass라는 클래스 객체를 생성했고 아래 with 문을 통해 printText( ) 메소드를 호출했다. with 구문을 통해 실행하니 __enter__( ) 메소드와 __exit__( ) 메소드가 실행된 것을 확인할 수 있다. 참고로 __exit__( ) 메소드의 매개변수인 exc_type, exc_val, exc_tb는 with 문을 빠져나오기 이전에 예외가 발생했을 때를 나타내는 정보라고 한다. 

 

  공부를 해보면서 알게된건 위와 같은 코딩 방식이 "Python Context Managers" 방식 중의 하나라고 한다. 다음에는 Context Managers(컨텍스트 매니저)라는 것에 대해 정리해볼 예정이다.

 


참고링크1  https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=wideeyed&logNo=221653260516 

 

[Python] with문 이해하기

Python의 with문에 대해서 알아보겠습니다. 자원을 획득하고 사용 후 반납해야 하는 경우 주로 사용합니다...

blog.naver.com

참고링크2 : https://sjquant.tistory.com/12

 

sjquant's devlog

sjquant의 개발 블로그

sjquant.tistory.com

 

 

728x90