반응형
CSV(Comma Separated Value)
- 쉼표로 나눠진 값을 저장한 데이터
- *.csv 형식으로 저장
- 텍스트 기반으로 서식 정보 등이 저장되지 않음
국어,영어,수학
90,80,100
CSV 파일을 읽고 CSV형 리스트로 만들기(read)
import csv, os
# sample.csv 파일이 있는 경로로 이동
os.chdir('/Users/**/downloads')
# csv 파일을 읽기 모드로 열기
f = open('sample.csv', 'r')
# scv 파일이 열리지 않는 경우 인코딩 형식 변경
# 원본 데이터가 utf-8이 아닌 경우 제대로 출력되지 않을 수 있음
# 그럴 땐 인코딩 형식을 cp949로 지정
f = open('sample.csv', 'r', encoding='utf-8')
# csv.reader() 함수를 사용하여 csv 파일을 읽기
reader = csv.reader(f)
# reader 객체를 사용하여 csv 파일의 내용을 읽기
for line in reader:
print(line) # 각 행을 출력
# 출력 결과
# ['국어', '영어', '수학']
# ['90', '80', '100']
# 파이썬에서 사용할 수 있도록 CSV 파일의 내용을 리스트로 변환
data = []
for line in reader:
data.append(line) # 각 행을 리스트에 추가
# 리스트의 내용을 출력
print(data) # []
# csv.reader(f)로 읽은 후에는 파일 포인터가 끝에 위치하므로, 다시 처음으로 이동해야 함
# 파일 포인터를 처음으로 이동, 반환 값 0
f.seek(0)
# 다시 csv.reader() 함수를 사용하여 csv 파일을 읽기
reader = csv.reader(f)
# csv 파일의 내용을 리스트로 변환
data = []
for line in reader:
data.append(line) # 각 행을 리스트에 추가
# 리스트의 내용을 출력
print(data) # [['국어', '영어', '수학'], ['90', '80', '100']]
CSV형 리스트를 CSV 파일로 만들기(write)
import csv
sample_data = [[
'국어', '영어', '수학'
], [
'90', '80', '100'
], [
'80', '70', '90'
], [
'70', '60', '80'
], [
'60', '50', '70'
], [
'50', '40', '60'
]]
# csv 파일을 쓰기 모드로 열기
# w: 쓰기 모드, a: 추가 모드, r: 읽기 모드, r+: 읽기/쓰기 모드
# newline='' : 줄바꿈 문자 처리, 이것을 추가하지 않으면 각 행 사이에 빈 줄이 추가되어 CSV 파일을 열었을 때 별도 편집을 해야 함
f = open('sample.csv', 'w', newline='')
# csv.writer() 함수를 사용하여 csv 파일을 쓰기
# delimiter : 구분자, 기본값은 쉼표(,), 사용할 CSV형 리스트의 원소가 쉼표(,)로 구분되어 있을 때 생략 가능
csvobject = csv.writer(f, delimiter=',')
# writerow() 함수를 사용하여 csv 파일에 한 행씩 쓰기
# writerow() : 한 행을 쓰기, writerows() : 여러 행을 쓰기
# 대부분의 경우 writerows()를 사용하여 여러 행을 한 번에 쓰는 것이 더 효율적
csvobject.writerows(sample_data)
# csv 파일을 닫기
# close() : 파일을 닫기
# close()를 사용하지 않으면 파일이 닫히지 않아서 다른 프로그램에서 파일을 열 수 없음
# close()를 사용하지 않으면 메모리 누수 발생 가능
f.close()
CSV 파일 ↔ CSV형 리스트 모듈 만들기
import csv
# csv파일을 csv형 리스트로 변환
def opencsv(filename):
f = open(filename, 'r')
reader = csv.reader(f)
output = []
for line in reader:
output.append(line)
return output
# writecsv: 기존 파일에 쓰는 함수, 해당 함수를 사용하는 경우 기존 파일에 새 내용으로 덮어쓰기 됨
# usecsv.writecsv('/users/**/downloads/sample.csv', sample_data)
# mac os의 다운로드 폴더 경로: '/users/**/downloads/*.csv'
def writecsv(filename, data):
with open(filename, 'w', newline='') as f:
csvobject = csv.writer(f, delimiter=',')
csvobject.writerows(data)
# writecsv_newfile: 새로운 파일을 생성하는 함수
def writecsv_newfile(filename, data):
try:
with open(filename, 'x', newline='') as f: # 'x' 모드 사용
csvobject = csv.writer(f, delimiter=',')
csvobject.writerows(data)
print(f"새 파일 '{filename}'이 생성되었습니다.")
except FileExistsError:
print(f"오류: '{filename}' 파일이 이미 존재합니다!")
open() 함수의 모드
- r: 읽기 모드, 파일이 존재해야 함(기본값)
- 파일을 열면 커서가 맨 앞에서 시작(seek(0)를 사용하지 않아도 처음부터 읽기/쓰기 가능)
- seek(0)을 사용하면 원하는 위치에 쓰기 가능
- 파일이 없으면 오류가 발생(FileNotFoundError)하므로 파일 존재 여부 검사 필요
import os
filename = "/users/**/downloads/sample.csv"
if not os.path.exists(filename):
print(f"오류: 파일 '{filename}'이 존재하지 않습니다.")
- w: 쓰기 모드, 파일이 존재하면 덮어씀, 없으면 새로 생성
- x: 새 파일 생성 모드, 파일이 이미 존재하면 오류 발생(FileExistsError)
- a: 추가 모드, 파일이 존재하면 끝에 내용 추가, 없으면 생성
- 커서를 이동할 수 없으며, 항상 파일 끝에서만 추가 가능
- b: 바이너리 모드, 이미지, 동영상, 오디오 등 바이너리 파일 읽기/쓰기
- 단독으로 사용되지 않고, rb, wb, ab등과 조합해서 사용
- b 자체는 파일을 이진(Binary) 형식으로 처리하겠다는 의미
- t: 텍스트 모드, 문자열 파일에 읽고 쓰기(기본값)
- +: 읽기 및 쓰기 모드, 파일을 읽고 쓸 수 있음(단독 사용 X, r+, w+, a+ 형태로 사용)
💡정리
- 기존 파일의 내용을 수정하고 싶다면 ⇒ r+
- 파일 끝에 새로운 데이터를 추가하고 싶다면 ⇒ a+
- 새로운 파일을 만들고 싶다면 ⇒ a+
seek(offset, whence)의 동작방식
seek() 함수는 파일 내에서 특정 위치로 커서를 이동할 수 있도록 두 개의 인자를 받음
- offset: 이동할 바이트(byte) 수
- whence(옵션, 기본값 0): 기준 위치
- 0 → 파일의 시작에서부터 offset만큼 이동
- 1 → 현재 커서 위치에서 offset만큼 이동
- 2 → 파일의 끝에서 offset만큼 이동
💡 정리
- 바이트 단위로 이동하는 경우 한글 깨짐
- 영어(ASCII)는 1바이트이지만, 한글(UTF-8)은 최소 2바이트 이상을 차지하므로 한글의 일부만 불러오면 깨지므로 문자 단위로 이동해야 함
- seek()대신 read()로 전체 문자열을 읽거나 바이트모드(rb)에서 decode()를 사용해야 함
한글이 깨지지 않게 처리하는 방법
'''
sample.txt의 내용은 다음과 같음
sample data
sample data
sample data
'''
with open("/users/**/downloads/sample.txt", "r", encoding="utf-8") as f:
content = f.read() # 전체 문자열을 읽음
print(content[5:]) # 문자열 기준으로 처리 (바이트 단위 X)
'''
출력결과
e data
sample data
sample data
'''
with open("/users/**/downloads/sample.txt", "rb") as f:
f.seek(6) # 특정 바이트 위치 이동
data = f.read(10) # 10바이트 읽기
print(data.decode("utf-8", errors="ignore")) # UTF-8로 변환 (깨진 문자 무시)
'''
출력결과
data
samp
'''
CSV 파일 안의 문자를 숫자로 전환하기
- 숫자 데이터를 받아 연산을 하고 싶은 경우에는 자료형이 정수(int) 혹은 실수(float)이어야 함
- 사용자 정의 모듈은 모든 자료형을 문자형(str)로 불러옴
- 문자형 → 정수형: int()
- 문자형 → 실수형: float()
💡정리
CSV 파일을 바로 숫자형으로 변경하는 경우 쉼표(,) 때문에 직접 바꿀 수 없음
re.sub() 함수를 사용해 쉼표(,)를 제거 후 int() 또는 float() 함수를 사용해 변경할 수 있음
import re # 정규식 모듈
str = '123,456'
# int(str) # ValueError: invalid literal for int() with base 10: '123,456'
# re.sub(r'\s+', ' ', str) # replace multiple spaces with a single space
# re.sub(바꿀문자열, 바뀔문자열, 대상문자열)
number = re.sub(',', '', str) # 123456
# change the type of number to int
int(number)
# check the type of number
type(number) # <class 'str'>
예외처리
import re
data = ['151,767', ' ', '11,093', '27,394', '123 456']
result = []
# 데이터에 빈 값이 있는 경우 예외 처리 하기
'''
try:
실행할 명령문
except:
예외 발생 시 처리할 명령문
'''
for i in data:
# 쉼표 제거 및 실수형으로 변환
try: data[data.index(i)] = float(re.sub(',', '', i))
# 실수형으로 변환할 수 없는 경우 예외 발생
except:
pass # pass는 아무것도 하지 않음
# 출력결과: 쉼표 제거 후 실수형으로 변환 가능한 값은 실수형으로 변환, 변환할 수 없는(예외)는 그대로 유지
print(data) # [151767.0, ' ', 11093.0, 27394.0, '123 456']
# pass 키워드를 사용하는 주요 이유
# 1. 임시 코드 작성: 나중에 구현할 함수나 클래스의 구조만 만들고 싶을 때
# 2. 빈 블록 유지: if, while, for 같은 제어문에서 문법 오류 없이 빈 블록을 유지하려고 할 때
# 3. 예외 처리: 특정 상황에서 아무 작업도 수행하지 않도록 만들고 싶을 때
사용자 정의 모듈 완성 코드
import csv,re
def opencsv(filename):
f = open(filename, 'r')
reader = csv.reader(f)
output = []
for line in reader:
output.append(line)
return output
def writecsv(filename, data):
with open(filename, 'w', newline='') as f:
csvobject = csv.writer(f, delimiter=',')
csvobject.writerows(data)
def convert_csv_to_float(csv_list):
result = []
if not isinstance(csv_list, list):
raise TypeError('입력값은 리스트여야 합니다.')
if not all(isinstance(i, list) for i in csv_list):
raise TypeError('리스트의 모든 요소는 리스트여야 합니다.')
for i in csv_list:
for j in i:
try:
result.append(float(re.sub(',', '', j)))
except ValueError:
result.append(j)
return result
사용자 정의 모듈 사용방법
- 작업 경로에 .py 파일을 복사해 놓고 필요할 때 임포트
- os 모듈이나 re 모듈처럼 어떤 폴더에서나 실행하려면 아나콘다가 설치된 폴더 안 Lib 폴더에 저장
- 파이썬만 설치한 경우(아나콘다 설치 X) Library/Frameworks/Python.framework/Versions/Current/lib/python3.xx/site-packages 폴더에 저장
site-packages 폴더
- pip install을 통해 설치한 패키지가 저장되는 곳
- Python이 자동으로 모듈을 찾는 기본 검색 경로 중 하나
- 필요하면 직접 추가한 사용자 정의 모듈도 이 폴더에 넣어 전역적으로 사용할 수 있음
- site-packages 폴더의 경로는 설치 방식에 따라 다름
- 시스템 Python: /Library/Frameworks/Python.framework/Versions/X.X/lib/pythonX.X/site-packages/
- Homebrew: /usr/local/lib/pythonX.X/site-packages/
- 사용자 전용 패키지(둘 중 하나 선택)
- ~/Library/Python/X.X/lib/python/site-packages/
- python -m site --user-site
반응형
'개발노트' 카테고리의 다른 글
파이썬으로 유튜브 영상 다운로드 앱 만들기 (1) | 2025.06.23 |
---|---|
파이썬 정규표현식 사용법과 예제 (0) | 2025.06.21 |
파이썬 웹 크롤링 – BeautifulSoup 사용법 (0) | 2025.06.19 |
TIL - S3 Presigned URL을 통해 이미지 파일 업로드 (0) | 2024.08.26 |
Spring Boot 실시간 알림 기능 구현 (0) | 2024.07.28 |