파이썬을 공부하다보면 다음과 같은 코드를 목격하게 된다.
with open("./corpus.txt", "r", encoding="utf-8") as fd:
corpus = fd.readlines()
대충 해석해보자면 with 다음에 오는 open("./corpus.txt", "r", encoding="utf-8")을 fd로 정의하는것으로 보인다.
그렇다면 왜 굳이 with as를 써준걸까?
이에 대한 구체적이니 이유는 다음 블로그에서 찾을 수 있었다.
위 블로그의 내용을 요약하자면,
리소스를 특정 구간에만 주고 싶은데 코드를 중복해서(try/except/finally)쓰기 보다는
with을 써서 해당 블록안에서만 리소스를 주고 나가면 해제한다.
그렇다면 주피터 노트북의 다른 셀에서 fd를 실행시키면 어떻게 나올까?
fd
<_io.TextIOWrapper name='./corpus.txt' mode='r' encoding='utf-8'>
분명 with 블록 안에서만 리소스를 준다고 했는데 어떻게 된걸까?
with open(...) as fd 구문은 fd 객체에 대해서 해당 with문을 벗어난 후에 자동으로 닫히도록 보장해준다.
즉 File Handle인 fd가 참조하던 실제 파일 리소스는 운영체제에 반환되어 닫히는건 맞다.
하지만 fd라는 변수 자체는 여전히 전역 스코프에 남아있다.
파이썬은 변수가 선언된 스코프 내에서 존재하므로, fd는 해당 TextIoWrapper 객체를 계속 참조하고 있는 것이다.
실제로 닫혔는지 다음 코드로 실험해봤다.
fd.read()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipython-input-28972991.py in <cell line: 0>()
----> 1 fd.read()
ValueError: I/O operation on closed file.
이로써, fd가 정상적으로 닫힌 파일을 계속 참조하고 있다는것을 알 수 있다.