1. CSV 파일이란?

🚀  Comma Separated Values의 약자로 '콤마로 분리한 값들'
🚀  데이터베이스나 스프레드시트 데이터를 저장하기 위해서 사용하는 형식
     

     ⚡️ 내부는 실제 콤마(,)를 이용해서 모든 항목이 구분되어 있으며

          콤마로 구성된 각 항목들이 테이블을 구성하는 각각의 데이터가 되는 방식
     ⚡️ 메모장에서는 텍스트로, 엑셀에서는 각 셀로 나누어서 보임

텍스트 파일
엑셀 파일


🚀  utf-8 형식으로 저장된 csv의 경우, 엑셀에서는 기본읽기로는 한글이 깨지는 경우가 있음
       ➡️  한컴 cell에서는 에러없이 잘 열림



1) 단점 ( 엑셀 형식의 파일과 비교했을 때 )

 

  a.  값에 유형이 없음. 모든 것은 다 문자열
  b.  글꼴 크기나 색상을 설정할 수 없음
  c.  여러 개의 워크시트를 가질 수 없음
  d.  셀의 너비나 높이를 지정할 수 없음
  e.  셀을 병합할 수 없음
  f.  그림이나 차트를 포함할 수 없음



2) 장점


  a.  단순함
 b.  많은 프로그램에서 지원을 하고, 텍스트 편집기에서 볼 수 있으며, 스프레드 시트 데이터를 표현하는 간단한 방법



3) 주의점


  ⚡️  텍스트로 구성되어 있어서, 각 줄에 대해 split(',')을 호출하여 쉼표로 구분된 값에서 문자열 리스트를 얻을 수 있음
         ➡️   csv 파일의 모든 쉼표가 두 셀의 경계를 나타내지 않고, 값의 일부인 경우도 있음
         ➡️  이런 잠재적인 문제 때문에 csv 파일을 읽거나 쓸 때 csv 모듈을 사용하는 것이 좋음

 


 

2. CSV 파일 읽기

🚀  csv 파일은 쉼표(,)로 데이터가 구분되어 있어서 문자열 처리 메소드를 활용하면 별도의 외부 모듈이 없이도 충분히 읽을 수 있음
🚀 
한 줄에 한 데이터가 있기 때문에 readline() 메소드로 한 줄씩 읽음
🚀 
콤마(,)로 분리하기 위해서 split() 메소드를 이용

 

학생명단.csv

student_list = []
with open('../input_2/학생명단.csv', 'rt', encoding='cp949') as file:
    file.readline()  # 학번, 이름, 주소, 연락처
    # readlines()는 한꺼번에 모두 읽고 커서가 맨 끝에 있어 더 이상 읽을 게 없어짐
    while True:
        line = file.readline()
        if not line:  # 더 이상 읽을 내용이 없으면 반복문을 빠져 나옴.
            break
        student = line.split(',')  # 안 넣으면 하나의 문자열로 생성되기 때문
        student_list.append(student)
print(student_list)  # 리스트 안에 리스트가 들어가 있는 형태
'''
[['10101', '김승별', '서울시 영등포구', '010-1111-1111\n'], 
['10102', '박나라', '서울시 여의도구', '010-2222-2222\n'], 
['10103', '최태욱', '서울시 강남구', '010-3333-3333\n'], 
['10104', '민기홍', '인천시 계양구', '010-4444-4444\n'], 
['10105', '이명숙', '경기도 과천시', '010-5555-5555\n']]
'''

 


 

 📌  csv 파일을 사용하다 보면 간혹 큰 따옴표(")를 이용해서 텍스트를 묶는 경우가 있음
        ➡️  큰 따옴표를 제거하기 위해서 회원명에 추가로 strip() 메소드를 사용

회원명단.csv

member_list = []
with open('../input_2/회원명단.csv', 'rt', encoding='cp949') as file:
    file.readline()
    while True:
        line = file.readline()
        if not line:
            break
        member = line.split(',')  
        member[0] = member[0].strip('"')  # 큰 따옴표를 제거
        member_list.append(member)
print(member_list)
'''
[['강나라', '필라테스', '25일\n'], ['나유라', '수영', '25일\n'], ['이상기', '헬스', '15일\n']]
'''

 

  👾  member[0]에는 큰 따옴표가 포함된 회원명이 저장되어 있기 때문에 member[0].strip('"')으로 큰 따옴표를 제거

 


📌  인코딩 시 영어는 문제가 없는데 한글의 경우 표현하는 방식이 2가지
     -  cp949 : 윈도우의 기본 인코딩. 예전 방식. 한글에만 특수화된 한국에서만 사용. 모든 한글을 표현하지 못함.
     -  uft-8 : 파이참의 기본 인코딩. 상대적으로 새로운 방식. 한글 및 기타 외국어 문자를 하나의 인코딩으로 모두 표현하기 개발

 


 

3. CSV 모듈

1) csv 모듈로 csv 파일 생성하기

 

 🚀  import csv 를 통해서 csv 파일을 쉽게 처리할 수 있는 csv 모듈을 사용

import csv

# w모드로 열고 생성된 파일 객체를 csv.writer() 메소드에 전달
# 그러면 csv 파일을 생성할 수 있는 객체가 생성되는데 이 객체를 이용해서
# writerow() 메소드를 호출하면 csv 파일에 데이터를 저장할 수 있음

with open('../output_02/차량관리_01.csv', 'w', newline='', encoding='cp949') as file:
    # delimiter=',' : ,콤마로 데이터 구분. tab을 사용하는 경우도 있음.tsv.
    csv_maker = csv.writer(file, delimiter=',')
    csv_maker.writerow([1, '08러1234', '2020-10-20,14:00'])
    csv_maker.writerow([2, '25다1234', '2020-10-20,14:10'])
    csv_maker.writerow([3, '28하1234', '2020-10-20,14:20'])
print('차량관리_01.csv 파일이 생성되었습니다.')

 


2) csv 모듈로 csv 파일 읽기

 🚀  csv 파일을 읽기 위해서는 r 모드로 파일을 열고 생성된 파일 객체를 csv.reader() 메소드에 전달
 🚀  csv.reader() 메소드는 csv 파일을 읽고 그 내용을 읽고 저장한 객체 iterator를 반환

with open('../output_02/차량관리_01.csv', 'r', newline='', encoding='cp949') as file:
    csv_reader = csv.reader(file, delimiter=',')
    for line in csv_reader:
        print(line)
        
'''
['1', '08러1234', '2020-10-20,14:00']
['2', '25다1234', '2020-10-20,14:10']
['3', '28하1234', '2020-10-20,14:20']
'''

차량관리_01.csv


 

3) reader 객체

 

🚀  csv 모듈은 별도의 설치없이 사용가능

🚀  csv 모듈을 사용해서 csv 파일을 읽으려면 다른 텍스트 파일처럼 open() 함수로 파일을 열어야 함

 

import csv

example_file = open('../input_2/example.csv', encoding='cp949')  # mode를 생략하면 rt가 기본값

# read() 대신 csv.reader() 함수에 전달. reader() 객체가 반환.
example_reader = csv.reader(example_file)

# list로 변환하여 값에 접근.
print(example_reader)  # <_csv.reader object at 0x100eadcb0>
example_data = list(example_reader)
print(example_data)
print(example_data[0][1])  # Apples
example_file.close()  # with 사용한 것이 아니기 때문에 닫아줘야 함

 


 

4)  for 반복문을 활용해 reader 객체로부터 데이터 읽기


🚀  csv 파일이 큰 경우에는 전체 파일을 한 번에 메모리에 로드하지 않고 for 반복문에서 reader 객체 사용
🚀  reader 객체는 한 번만 사용가능하기 때문에 다시 사용하려면 새로 reader 객체 생성

example_file = open('../input_2/example.csv', encoding='cp949')
example_reader = csv.reader(example_file)

print('example.csv 출력')
for row in example_reader:
    # 각 행의 번호를 얻으려면 reader 객체의 line_num 변수를 사용
    print(f'Row #{str(example_reader.line_num)} {str(row)} {str(row[0])}')
example_file.close()
print('=' * 20)

 


5) writer 객체

 

🚀  writer 객체를 사용하면 데이터를 csv 파일에 저장할 수 있음

output_file = open('../output_02/output.csv', 'w', newline='', encoding='cp949')
# newline = '' : 빈줄이 들어가는 것 방지
output_writer = csv.writer(output_file)  # csv.writer에 전달할 객체 생성.
output_writer.writerow(['spam', 'eggs', 'bacon', 'ham'])  # writer.writerow() : 리스트에 인자를 전달
output_writer.writerow(['hello, world!', 'eggs', 'bacaon', 'ham'])
output_writer.writerow([1, 2, 3, 3.141592, 4])
output_file.close()

output.csv


 

4.  키워드 인자 delimiter와 lineterminator

🚀  탭문자로 셀을 구분하고 줄 간격을 한 줄씩 띄우려는 상황이라면 구분자(delimiter)와 줄 끝 문자(lineterminator)를 변경
🚀  delimiter의 기본값은 쉼표이고, lineterminator의 기본값은 개행문자
🚀  셀들이 탭으로 구분되어 있기 때문에 탭으로 구분된 값을 의미하는 .tsv 파일 확장자 사용

csv_file = open('../output_02/example.tsv', 'w', newline='', encoding='cp949')
csv_writer = csv.writer(csv_file, delimiter='\t', lineterminator='\n\n')
csv_writer.writerow(['apples', 'oranges', 'grapes'])
csv_writer.writerow(['eggs', 'bacon', 'ham'])
csv_writer.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam'])
csv_file.close()

 


 

5. csv 객체의 DictReader와 DictWriter

🚀  헤더 행이 있는 csv 파일의 경우 reader나 writer 객체보다 DictReader나 DictWriter 객체를 사용하는 것이 작업하기 편함

 

  ⚡️  DictReader 객체

        a. row를 딕셔너리 객체로 설정하고 

        b. 첫 번째 행에 있는 정보를 건너 뜀 

        c. 첫 번째 행에 있는 정보를 키값으로 사용

example_file = open('../input_2/example_with_header.csv', encoding='cp949')
example_dict_reader = csv.DictReader(example_file)

print('example_with_header.csv 출력')
for row in example_dict_reader:
    #print(row)
    print(f'{row["Timestamp"]}, {row["Fruit"]}, {row["Quantity"]} ')
print('=' * 20)

example_with_header.csv


 

🚀  헤더 행이 없는 파일의 경우  DictReader() 생성자의 두 번째 인자로 헤더 이름을 지어서 전달

example_file = open('../input_2/example.csv')
example_dict_reader = csv.DictReader(example_file, ['time', 'name', 'amount'])
print('example.csv 출력')
for row in example_dict_reader:
    print(f'{row["time"]}, {row["name"]}, {row["amount"]} ')
print('=' * 20)

 


 

 

  ⚡️ DictWriter 객체는 csv 파일을 생성하기 위해 딕셔너리를 사용

       -  파일에 헤더 행을 넣고 싶으면 writeheader()를 호출

       -  writerow() 메서드를 호출하여 각 행을 쓸 수 있는데, 이 때 딕셔너리를 사용
            ➡️ 딕셔너리의 키는 헤더이고, 딕셔너리의 값은 파일에 쓰려는 데이터가 들어감

output_file = open('../output_02/output_with_header.csv', 'w', newline='', encoding='cp949')
output_dict_writer = csv.DictWriter(output_file, ['Name', 'Pet', 'Phone'])

output_dict_writer.writeheader()

output_dict_writer.writerow({'Name': 'Alice', 'Pet': 'cat', 'Phone': '555-1234'})
output_dict_writer.writerow({'Name': 'Bob', 'Phone': '555-9999'})  
# 누락된 키는 빈 상태로 나옴.
output_dict_writer.writerow({'Phone': '555-5555', 'Name': 'Carol', 'Pet': 'dog'})  
# 순서는 중요하지 않음.
output_file.close()

output_with_header.csv

 

 

+ Recent posts