4.1 파일 닫기와 오류 처리
가끔 파일을 읽을 때 오류나 예외가 발생하고 파일이 닫히지 않을 수 있어.
이것은 잠재적으로 메모리 누수 또는 file handler
의 누수로 이어질 수 있어.
그래서 파일 작업을 try-except
블록으로 감싸야 해.
예를 들어, 너의 코드가 이렇게 있었어:
file = open('example.txt', 'a') # 파일을 엽니다
file.write("This is a new line added to the file.")
file.close() # 파일을 닫습니다
이걸 try-except
블록으로 감싸야 해:
try:
file = open('example.txt', 'a') # 파일을 엽니다
file.write("This is a new line added to the file.")
file.close() # 파일을 닫습니다
except FileNotFoundError:
print("File not found")
file.close() # 파일을 닫습니다
close()
메서드를 두 번 쓰지 않으려면 이를 finally
블록에 넣을 수 있어:
try:
file = open('example.txt', 'a') # 파일을 엽니다
file.write("This is a new line added to the file.")
except FileNotFoundError:
print("File not found")
finally:
file.close() # 파일을 닫습니다
이 코드는 깔끔해 보이지만... 작동하지 않아. 왜냐하면 변수 file
이 try
블록에서만 정의되어 있어 except
와 finally
블록에서 접근할 수 없어.
그래서 변수를 더 높은 수준에서 정의해야 해:
file = None
try:
file = open('example.txt', 'a') # 파일을 엽니다
file.write("This is a new line added to the file.")
except FileNotFoundError:
print("File not found")
finally:
file.close() # 파일을 닫습니다
이것은 더 나은 해결책이지만 여전히 문제점이 있어. 예를 들어, 파일이 열리지 않은 경우 변수 file
에는 None
이 남아 있을 거야. 그러면 파일을 닫으려 할 때 오류가 발생할 거야 — 존재하지 않는 객체의 close()
메서드를 호출하려는 시도가 될 거야.
그러므로, close()
메서드를 호출하기 전에 확인을 추가해야 해:
file = None
try:
file = open('example.txt', 'a') # 파일을 엽니다
file.write("This is a new line added to the file.")
except FileNotFoundError:
print("File not found")
finally:
if file:
file.close() # 파일을 닫습니다
3줄 코드가 9줄로 변한 것에 놀라지 않는다면, 너 혼자가 아니야. 다행히, 이 문제에 대한 이미 준비된 해결책이 있어, 우리는 곧 그것에 대해 이야기할 거야.
4.2 with
연산자
Python의 with
연산자는 파일과 같은 리소스를 관리하는 편리한 방법을 제공하면서 with
블록이 완료된 후 자동으로 파일을 닫아줘. 이는 코드 작성을 단순화하고 닫히지 않은 파일과 같은 리소스 누수를 방지해줘.
with
연산자의 일반적인 문법:
with 표현식 as 변수:
변수와 작업
with
연산자는 코드 블록 실행을 컨텍스트 매니저로 감싸는 데 사용돼. with
연산자를 사용하면 Python은 자동으로 컨텍스트 매니저 객체의 __enter__()
와 __exit__()
메서드를 호출하여 리소스 관리를 쉽게 해줘.
with
를 사용하여 파일 작업을 하는 예:
with open('example.txt', 'w') as file:
file.write("Hello, World!\n")
file.write("This is a test file.\n")
이 예에서 example.txt
파일은 쓰기 모드로 열리고, 파일 이름은 file
변수와 연결돼. with
내부의 코드 블록은 모든 쓰기 작업이 수행된 후 파일을 자동으로 닫아줘.
4.3 파일의 자동 닫기
with
연산자의 주요 이점 중 하나는 코드 블록이 완료된 후 파일을 자동으로 닫아준다는 거야. 이는 예외가 발생한 경우에도 발생하며, 코드를 더 안전하고 신뢰할 수 있게 만들어줘.
파일 자동 닫기의 예:
try:
with open('example.txt', 'w') as file:
file.write("Hello, World!\n")
file.write("This is a test file.\n")
# 파일이 여전히 닫히는지 확인하기 위한 예외
raise Exception("Something went wrong")
except Exception as e:
print(f"Caught an exception: {e}")
# 이 지점에서 파일은 이미 닫혀있습니다
파일 작업을 할 때는 항상 with
연산자를 사용해. 이게 간단하고 많은 오류를 피할 수 있어.
4.4 with
연산자의 내부
with
연산자의 작동 원리는 컨텍스트 매니저로 사용되는 클래스에 구현된 __enter__()
와 __exit__()
메서드에 있어.
with
연산자를 사용하려면 객체는 __enter__()
와 __exit__()
메서드를 구현해야 해. 이 메서드들은 컨텍스트 진입 및 종료 시의 동작을 정의해.
메서드 __enter__()
__enter__()
메서드는 with
블록에 진입할 때 호출돼.
리소스 초기화를 수행하고 as
뒤에 지정된 변수에 바인딩할 객체를 반환해.
메서드 __exit__()
__exit__()
메서드는 with
블록에서 나올 때 호출돼. 이 메서드는 리소스 해제나 파일 닫기와 같은 완료 작업을 수행해. 메서드는 예외가 발생한 경우에 대한 정보를 포함하는 exc_type
, exc_val
, exc_tb
라는 세 개의 인수를 받아.
-
exc_type
: 예외 유형 (예:ZeroDivisionError
). -
exc_val
: 예외 값 (예: 오류 메시지). exc_tb
: 예외 스택 추적.
__exit__()
메서드가 True
를 반환하면, 예외는 억제될 거야. False
를 반환하면, 예외가 다시 발생할 거야.
예제:
class MyContextManager:
def __enter__(self):
print("Entering the context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
print(f"An exception occurred: {exc_type}, {exc_val}")
return False # 예외가 억제되지 않습니다
with MyContextManager() as manager:
print("Inside the with block")
GO TO FULL VERSION