12 Python File System
이번 시간에는 다음 내용에 대해 학습했습니다.
- 파이썬 파일 시스템
FS의 주요 메서드와 함수 인자 CSV파일 형식과 조작- 디버그
Debug모드의 활용
마찬가지로 강의 내용과 스스로 학습한 내용을 함께 정리했습니다. 개인적으로 이해하기 쉬운 순서로 글을 편집해서 실제 강의 내용 순서와 다를 수 있습니다.
read(): 파일 전체를 하나의 문자열로 읽는 함수입니다. nodeJS의 fs.readFileSync()와 유사합니다. - 참조: nodeJS는 Javascript 기반의 런타임 환경입니다. 브라우저, 서버 양측에서 모두 사용될 수 있습니다. - NodeJs의 fs는 File System을 관리하기 위한 내장 모듈입니다. - fs.readFileSync()와 fs.readFile()은 반환값은 같지만 동기 sync/비동기 async 방식에 차이가 있습니다.
open(): 파일은 반드시 close()로 닫아야 하지만, with 구문을 사용하면 파일을 자동으로 닫을 수 있어 편리합니다.
- 함수 인자
Params: - `open(file, mode, buffering | encoding | errors | newline )
file(필수): 열고자 하는 파일의 경로와 이름입니다.mode(선택): 파일을 어떤 목적으로 열지 지정하는 모드입니다.'r': 읽기 모드 (기본값).'w': Write 쓰기 모드 (파일이 없으면 생성, 있으면 덮어씀).'a': 추가 모드 (파일 끝에 내용을 덧붙임).'b': 바이너리 모드 (바이트 단위로 처리).'t': 텍스트 모드 (문자열 단위로 처리, 기본값).'+': 읽기와 쓰기 모두 가능.- 이 모드들은 조합 가능합니다 (예:
'rb'는 바이너리 읽기 모드)
- 옵션 인자
Optional Paramsbuffering=: 파일 버퍼링 정책을 설정합니다. 기본값은 -1 (시스템 기본값) 입니다.encoding=: 파일을 읽거나 쓸 때 사용할 인코딩을 지정합니다. 시스템 기본 인코딩을 사용하려면 None으로 둡니다.errors=: 인코딩 및 디코딩 시 발생하는 오류를 어떻게 처리할지 설정합니다. 기본값은 None입니다.newline=: 개행 문자를 어떻게 처리할지 설정합니다. 기본값은 None입니다.
개인적으로 Javascript에선 함수 인자의 순서가 중요한 반면,
옵션 인자 Optional Param에 buffering= 이런 식으로 순서와 상관없이 사용할 수 있는 점이 신선했습니다.
함수 인자의 순서가 복잡해지면 객체(dict)를 생성하여 쓰곤 했는데, 좋은 방법이 아닐 때가 종종 있습니다.
close() 메서드 실행:
파이썬에서 close()를 프로그램 종료 시 자동으로 실행하도록 보장하는 몇 가지 방법이 있습니다.
주로 with 문, try...finally 블록, atexit 모듈을 사용합니다.
파이썬 statement문법을 익히기 위해 함께 살펴보겠습니다.
withwith문은 블록을 벗어나는 순간 리소스를 자동으로 닫아주는 가장 깔끔하고 권장되는 방법입니다. 파일, 소켓, 데이터베이스 연결 등open()과close()가 필요한 모든 상황에 적합합니다. 장점: 간결하고 가독성이 높습니다. 예외 발생 여부와 관계없이 리소스가 안전하게 해제됩니다. 예시 (파일 처리):
with open('test.txt', 'r') as f:
# 파일 작업 수행
content = f.read()
print(content)
# with 블록이 끝나면 f.close()가 자동으로 호출됨
try...finallytry...finally는 예외 발생 여부와 관계없이 finally 블록의 코드를 반드시 실행하도록 보장합니다.with문을 사용할 수 없는 상황이나 더 복잡한 로직이 필요할 때 유용합니다. 장점: 예외 처리와 리소스 해제를 함께 관리할 수 있습니다. 예외가 발생하더라도 정리 작업이 실행됩니다. 예시 (소켓 처리):
import socket
s = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 소켓 작업 수행
s.sendall(b'Hello')
except Exception as e:
print(f"오류 발생: {e}")
finally:
if s:
s.close() # 소켓이 생성되었으면 닫음
# 이 코드는 예외 발생 여부와 관계없이 항상 s.close()를 시도
atexit모듈 사용atexit모듈은 파이썬 프로그램이 정상적으로 종료될 때(예:sys.exit()호출 또는 스크립트 끝에 도달) 특정 함수를 실행하도록 등록할 수 있습니다. 단,os._exit()와 같은 비정상 종료 시에는 호출되지 않을 수 있습니다. 장점: 프로그램 전체 종료 시점에 정리 작업을 수행할 수 있습니다. 여러 함수를 등록하여 순서대로 실행시킬 수 있습니다. 예시 (정리 함수 등록):
import atexit
def cleanup():
print("프로그램이 종료됩니다. 정리 작업을 실행합니다.")
# 필요한 정리 작업(예: 파일 닫기, 연결 해제 등) 수행
# ...
atexit.register(cleanup)
print("메인 프로그램 시작...")
# 메인 로직 수행
# ...
print("메인 프로그램 종료.")
__del__()메서드 사용 (주의 필요) 클래스의 소멸자 역할을 하는__del__()메서드는 인스턴스가 가비지 컬렉터에 의해 삭제될 때 호출됩니다. 그러나 파이썬의 가비지 컬렉션은 호출 시점이 보장되지 않으므로, 중요한 리소스 정리 작업에는 이 방법을 사용하지 않는 것이 좋습니다. 사용을 권장하지 않는 이유:__del__()이 언제 호출될지 예측할 수 없습니다. 순환 참조가 발생하면 호출되지 않을 수 있습니다. 예시 (참고용):
class MyResource:
def __init__(self):
print("리소스를 할당합니다.")
def __del__(self):
print("리소스를 해제합니다.")
res = MyResource()
del res # 명시적으로 삭제하면 호출될 수 있음
# 프로그램 종료 시 가비지 컬렉터에 의해 호출될 수도 있음
CSV
0930 파이썬 실습 시간에는 CSV 파일을 생성 및 조작하는 법을 배웠습니다.
다음 코드는 csv 파일에 list 타입 데이터를 인자 parameter으로 받아 각각의 칼럼에 입력합니다.
# 인코딩 타입을 정확히 작성해야 글자 등이 안깨짐
def to_csv_2(_list):
file = open("data_2.csv", "w", encoding="utf-8", newline="")
csvfile = csv.writer(file)
for row in _list:
csvfile.writerow(row)
# to_csv(['1', '2', '3', '4'])
to_csv_2([["1", "2"], ["3", "4"]])
Debug 모드
둘째로, PyCharm의 디버그 모드에 대해 학습했습니다.
이 기능을 통해 함수가 실행될 때 중단점에서 코드를 중단|재개할 수 있습니다.
디버거에는 중단점에서 변수의 상태값과 파일 시스템까지 볼 수 있어 상당히 유용합니다.
개인적으로 반복문 내부에서 상태값 변화를 추적하는 데에 유용함을 느꼈습니다.
Mac 기준으로 run debug: ^D로 실행할 수 있습니다.
def to_csv(_list):
# 'w' 모드이므로 실행마다 새로운 csv 파일로 덮어쓰기가 됩니다.
file = open("data_1.csv", "w", encoding="utf-8", newline="")
# 여기서 중단점을 실행
print(f"---bf---")
for row in _list:
write_row = ""
for element in row:
# 중단점 2
print(f"row cur: {row}")
write_row += f"{element}, "
file.write(write_row + "\n")
file.close()
to_csv(["1", "2", "3", "4"])
추가적으로 디버거 Step Into와 Step Over를 배웠습니다.
가장 큰 차이점은 함수 호출을 만났을 때 디버깅의 진입 범위입니다.
Step Over: 현재 코드 라인을 실행하고 다음 라인으로 이동합니다.- 현재 라인에 함수 호출이 있더라도 그 함수 내부로는 들어가지 않고, 함수 전체를 한 번에 실행한 뒤 다음 코드로 넘어갑니다.
Step Into: 현재 코드 라인을 실행하되, 함수 호출을 만나면 그 함수 내부로 진입하여 함수 코드의 첫 번째 라인부터 한 단계씩 실행을 추적합니다.