개요
csv에 인터넷에서 수집한 데이터를 저장하고 그 csv 파일에 적힌 데이터를 파이썬에서 다시 읽으려면 어떻게 해야될까?
csv란?
엑셀 파일 형식처럼 데이터가 저장된 파일이다.
주의할 점은 엑셀과 같은 프로그램으로 csv를 읽을 때 유니코드 방식으로 읽어야 한다!
파이썬에서 csv 파일을 작성해보자
쓰는 건 그렇게 어렵지 않다고 생각해서 그렇게 길게 이야기하지 않으려고 한다.
import csv
with open("samples.csv", "w", encoding="utf8", newline='\n') as f:
fieldnames = ["name", "country", "age"] # field의 제목이 되는 문자열들을 미리 저장해둔다.
wr = csv.DictWriter(f, fieldnames=fieldnames) # csv에 데이터들을 딕셔너리 형식으로 정보를 전달해주기 위해 작성한다.
wr.writeheader() # csv 파일 맨 위에 헤더를 적어준다. 쓰지 않으면 헤더가 작성되지 않는다.
for name, country, age in player_data:
wr.writerow({"name":name, "country":country, "age":int(age)}) # csv에 각 열에 맞는 데이터 쓰기
https://www.knowledgehut.com/tutorials/python-tutorial/python-csv writeheader의 역할!
여기서 헷갈렸던 건, writeheader가 무슨 일을 하냐는 것이었다.
하는 일은 아주 간단하게 csv 파일의 맨 위에 헤더를 작성해주는 것이다.
작성할 때 기반이 되는 데이터는 fieldnames이다!
이걸 헷갈렸던 이유는, csv의 메소드인 writer를 사용하지 않고 다른 방식으로 썼을 때 writeheader를 쓰지 않아도 헤더가 작성이 됐었다.
그래서 DictWriter로 개선한 후에도 writeheader가 왜 있는 거지 싶었다.
하지만 DictWriter로 개선한 후에 writeheader를 적어주지 않으면 헤더가 작성되지 않는다.
역시 헷갈릴 때는 그냥 해보는 게 최고다.
파이썬에서 csv 파일을 읽어보자
사실 읽는 건 어렵지 않다.
그런데 csv에 저장되어 있는 pair 그대로, key-value의 pair 그대로 들고 오는 게 어려웠다.
처음에 내가 작성했던 코드 파일을 보자.
클래스의 생성자 부분을 따온 것이다.
def __init__(self, file_name: str="samples.csv"):
#1 self.__file = open(file_name, "r")
#2 self._file_data = []
self.__length = 0
#3 lines = self.__file.readlines()
for i, line in enumerate(lines):
if i != 0:
#4 line = line.strip().split(",")
#5 self._file_data.append((line[0], line[1], line[2]))
self.__length = i
self.__file.close()
번호가 라벨링된 순서대로 살펴보자.
#1 파일을 열고 그 객체를 self.__file에 저장한다.
#2 csv 파일에 있는 데이터를 담기 위한 배열을 선언한다.
#3 readlines를 이용해서 csv 파일 안의 모든 데이터를 문자열 리스트로 반환하여 lines에 저장한다. readlines를 이용해서 데이터를 저장한 후 for문을 이용해서 읽으면 한 줄씩 읽을 수 있기 때문이었다. 여기서부터 사고는 시작됐다.
#4 총 3개의 열을 가진 데이터를 데이터 하나당 튜플 한 묶음으로 묶어서 배열에 넣기위해 쉼표를 기준으로 split을 했다.
#5 열마다 데이터를 쪼개서 배열에 저장한다.
이렇게 하면 안 된다.
1. #4가 가장 치명적이다. 물론 #3도 치명적이지만 #4가 가장 치명적이라고 생각한다.
왜냐, split을 써버리면 인자로 들어온 그 문자열은 사라지고 그 문자열이 있었던 자리를 기준으로 리스트가 만들어진다.
중요한 건 문자열이 사라진다는 거다. 문자열이 사라진다는 건 데이터 훼손이기 때문에 절대로 이렇게 하지 말자.
2. 일단 우리의 목적은 csv 파일의 데이터를 읽는 것이었다. 그런데 나는 csv 파일을 읽고 쓰는 데 도움을 주는 import csv 라이브러리는 무시하고 기본 메소드로 파일을 읽었다.
이렇게 처음부터 안 적고 csv 라이브러리를 사용했다면 헷갈리지 않았을 것이다.
그래도 괜찮다 이렇게 새로운 걸 배웠으니까. 틀린 덕분에 배웠으니까.
진짜 csv 파일을 읽어보자
import csv
class Player:
def __init__(self, file_name: str="samples.csv"):
self.__file = open(file_name, "r")
#1 self.__reader = csv.reader(self.__file, delimiter=",")
self._file_data = []
self.__length = 0
for i, (name, country, age) in enumerate(self.__reader):
if i != 0:
#2 self._file_data.append((name, country, int(age)))
self.__length = i
self.__file.close()
delimiter에 대한 설명과 csv.reader의 파라미터에 대한 설명은 https://m.blog.naver.com/real_77/221224637207를 참고하자.
delimiter만 말하자면, csv 파일의 데이터가 무슨 기호로 구분지어져 있는지 확인시켜주는 것이다.
csv 라이브러리를 불러서 데이터를 읽으니 코드 작성도 훨씬 편하고 이해하기도 좋게 코드를 작성할 수 있다.
가장 중요한 건 데이터 훼손이 없다!
csv 파일을 읽을 때든 Yaml을 읽을 때든 파일에 맞는 라이브러리가 있는지 확인하는 걸 잊지 말아야겠다.
약간의 도움을 받은 stack overflow https://stackoverflow.com/questions/27574146/open-file-in-init-python
읽는 부분에서 많은 도움을 줬던 블로그 https://ourcstory.tistory.com/48
'Hacks' 카테고리의 다른 글
다중집합 (0) | 2022.11.15 |
---|---|
위상정렬 (0) | 2022.11.14 |
클로저 (0) | 2022.11.10 |
파이썬 itertools의 조합 Combinations 구현 (0) | 2022.11.10 |
파이썬 itertools의 순열 Permutations 구현 (0) | 2022.11.10 |