본문 바로가기

Hacks

파이썬에서 csv 파일에 데이터를 쓰고, 읽어오기

개요

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