파이썬 파일 읽기 및 쓰기(2)

윤태영·2023년 11월 26일
0
post-thumbnail

이미지 출처: https://wikidocs.net/192339

csv파일이라고 많이 들어보셨죠? 서로 다른 프로그램에서 데이터를 주고받을때 주로 csv파일 형식으로 전달합니다. xml,json 같은 형식도 있지만 파이썬에서는 내부적으로 csv파일을 쓰거나 읽을 수 있는 그런 패키지를 제공합니다.

파일 Write 실습(2)

  • csv파일 설명
  • csv.reader
  • csv.DictReader
  • csv.writer
  • csv 파일 전체 실습

CSV : MEME - text/CSV (CSV의 MEMETYPE이라고 있는데 이것은 text/csv를 표현한다.
(웹에서 보는 것은 html)

text/CSV문구가 웹 통신을 만드는데 나왔다면 이거 csv 파일로 통신해야한다고 알아야한다.

먼저 csv파일들을 살펴보겠습니다.

-test1.csv-

첫번째 1행이 header라고 불리는 열머리글 입니다.
국가이름과, 국가코드를 의미하는 데이터가 있습니다.
콤마로 구분되어 있으며 250개정도의 나라가 있습니다.

Name,Code - header
Afghanistan,AF
Åland Islands,AX
Albania,AL
Algeria,DZ
American Samoa,AS
Andorra,AD
Angola,AO
Anguilla,AI
Antarctica,AQ
Antigua and Barbuda,AG
Argentina,AR
Armenia,AM
Aruba,AW
Australia,AU
Austria,AT
Azerbaijan,AZ
Bahamas,BS
Bahrain,BH
Bangladesh,BD
Barbados,BB
Belarus,BY
....................
....................
....................

-test2.csv-

csv는 무조건 콤마로 구분될 필요는 없습니다.

Name|Code
Afghanistan|AF
Åland Islands|AX
Albania|AL
Algeria|DZ
American Samoa|AS
Andorra|AD
Angola|AO
Anguilla|AI
Antarctica|AQ
Antigua and Barbuda|AG
Argentina|AR
Armenia|AM
Aruba|AW
Australia|AU
Austria|AT
Azerbaijan|AZ
Bahamas|BS
Bahrain|BH
Bangladesh|BD
Barbados|BB
Belarus|BY

예1

test1.csv파일을 읽어와 보겠습니다.

# csv파일 관련 처리를 도와주는 csv 패키지를 import한다.
# 인코딩은 기본으로 utf-8로 지정되있기에 적지 않겠습니다.
# csv파일을 읽어 올때는 reader로 연결해준다. 이렇게 파일과 연결된 오픈 함수에서의 변수를 reader에다가 인자로 넘겨주면 csv파일을 사용할 준비완료
# 속성에 __iter__가 있으니 for문에서도 사용가능하구나!
import csv
with open('./resource/test1.csv', 'r') as f:
    reader = csv.reader(f) 
    # next(reader) # Header skip - 내용만 보고싶을때 사용
    print(reader) # 객체확인
>>>> <_csv.reader object at 0x000001CF06028BE0> # 읽어온 그 자체로는 오브젝트이기에 아직은 내용을 확인할 수 없다.
	# 타입 확인
    print(type(reader))
>>>> <class '_csv.reader'>
	# 속성확인
    print(dir(reader)) 
>>> ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'dialect', 'line_num']

내용 출력
값을 리스트로 가져옵니다.
출력 값이 너무길어서 생략했습니다.

import csv
with open('./resource/test1.csv', 'r') as f:
    reader = csv.reader(f) 
    for c in reader:
        print(c)
>>>
['Name', 'Code']
['Afghanistan', 'AF']   
['횇land Islands', 'AX']
['Albania', 'AL']       
['Algeria', 'DZ']
['American Samoa', 'AS']
['Andorra', 'AD']
['Angola', 'AO']
['Anguilla', 'AI']
['Antarctica', 'AQ']
['Antigua and Barbuda', 'AG']
['Argentina', 'AR']
['Armenia', 'AM']
['Aruba', 'AW']
['Australia', 'AU']
['Austria', 'AT']
['Azerbaijan', 'AZ']
['Bahamas', 'BS']
['Bahrain', 'BH']
['Bangladesh', 'BD']
['Barbados', 'BB']
['Belarus', 'BY']
['Belgium', 'BE']
['Belize', 'BZ']
['Benin', 'BJ']
['Bermuda', 'BM']
['Bhutan', 'BT']
['Bolivia, Plurinational State of', 'BO']
['Bonaire, Sint Eustatius and Saba', 'BQ']
['Bosnia and Herzegovina', 'BA']

만약 위의 헤더를 제외한 내용만 가져오고 싶다면??

import csv
with open('./resource/test1.csv', 'r') as f:
    reader = csv.reader(f) 
    next(reader) # Header Skip
    for c in reader:
        print(c)
>>>
['Afghanistan', 'AF']   
['횇land Islands', 'AX']
['Albania', 'AL']       
['Algeria', 'DZ']
['American Samoa', 'AS']
['Andorra', 'AD']
['Angola', 'AO']
['Anguilla', 'AI']
['Antarctica', 'AQ']
['Antigua and Barbuda', 'AG']
['Argentina', 'AR']
['Armenia', 'AM']
['Aruba', 'AW']
['Australia', 'AU']
['Austria', 'AT']
['Azerbaijan', 'AZ']
['Bahamas', 'BS']
['Bahrain', 'BH']
['Bangladesh', 'BD']
['Barbados', 'BB']
['Belarus', 'BY']
['Belgium', 'BE']
['Belize', 'BZ']
['Benin', 'BJ']
['Bermuda', 'BM']
['Bhutan', 'BT']
['Bolivia, Plurinational State of', 'BO']
['Bonaire, Sint Eustatius and Saba', 'BQ']
['Bosnia and Herzegovina', 'BA']

만약 출력되는 리스트 값을 문자열로 가져오고 싶다면?
여러분이 csv파일을 보고싶은 형식으로 포맷팅을 해서 볼 수 있습니다.

import csv
with open('./resource/test1.csv', 'r') as f:
    reader = csv.reader(f) 
    next(reader) # Header Skip
    for c in reader:
    	print((' : '.join(c)) 프린트의 공백을 join 이라는 함수에 더해서 c를 하겠다.
>>>>
Afghanistan : AF
횇land Islands : AX
Albania : AL
Algeria : DZ
American Samoa : AS
Andorra : AD
Angola : AO
Anguilla : AI
Antarctica : AQ
Antigua and Barbuda : AG
Argentina : AR
Armenia : AM
Aruba : AW
Australia : AU
Austria : AT
Azerbaijan : AZ
Bahamas : BS
Bahrain : BH
Bangladesh : BD
Barbados : BB
Belarus : BY
Belgium : BE
Belize : BZ
Benin : BJ
Bermuda : BM
Bhutan : BT
Bolivia, Plurinational State of : BO
Bonaire, Sint Eustatius and Saba : BQ
Bosnia and Herzegovina : BA
Botswana : BW
Bouvet Island : BV
Brazil : BR
British Indian Ocean Territory : IO
Brunei Darussalam : BN
Bulgaria : BG
Burkina Faso : BF

예2

두번째 인자로 구분자 del(구분자)을 넣어줄 수 있다. 예제 1에서는 csv의 기본값은 콤마이기에 적지 않은것

with open('./resource/test2.csv', 'r') as f:
    reader = csv.reader(f, delimiter='|') 
    for c in reader:
        print(c)
>>>
['Afghanistan', 'AF']   
['횇land Islands', 'AX']
['Albania', 'AL']       
['Algeria', 'DZ']
['American Samoa', 'AS']
['Andorra', 'AD']
['Angola', 'AO']
['Anguilla', 'AI']
['Antarctica', 'AQ']
['Antigua and Barbuda', 'AG']
['Argentina', 'AR']
['Armenia', 'AM']
['Aruba', 'AW']
['Australia', 'AU']
['Austria', 'AT']
['Azerbaijan', 'AZ']
['Bahamas', 'BS']
['Bahrain', 'BH']
['Bangladesh', 'BD']
['Barbados', 'BB']
['Belarus', 'BY']
['Belgium', 'BE']
['Belize', 'BZ']
['Benin', 'BJ']
['Bermuda', 'BM']
['Bhutan', 'BT']
['Bolivia, Plurinational State of', 'BO']
['Bonaire, Sint Eustatius and Saba', 'BQ']
['Bosnia and Herzegovina', 'BA']

예3

딕셔너리로 읽어보겠습니다.
reader가 아니라 DictReader를 사용하자.
name과 code를 정확히 구분해주었습니다 신기하게,
키와 밸류 형태로 order, 정렬된 dictionary클래스 형태로 반환해주는것을 보실 수 있습니다.

import csv
with open('./resource/test1.csv', 'r') as f:
    reader = csv.DictReader(f)
    # 확인
    print(reader)   
    print(type(reader))
    print(dir(reader))
    print()
	for c in reader: # 딕셔너리 형태로 csv파일을 가져오면 column name을 , field name을 살릴 수 있다.
    	print(c)
>>>
{'Name': 'Afghanistan', 'Code': 'AF'}
{'Name': '횇land Islands', 'Code': 'AX'}
{'Name': 'Albania', 'Code': 'AL'}
{'Name': 'Algeria', 'Code': 'DZ'}
{'Name': 'American Samoa', 'Code': 'AS'}
{'Name': 'Andorra', 'Code': 'AD'}
{'Name': 'Angola', 'Code': 'AO'}
{'Name': 'Anguilla', 'Code': 'AI'}
{'Name': 'Antarctica', 'Code': 'AQ'}
{'Name': 'Antigua and Barbuda', 'Code': 'AG'}
{'Name': 'Argentina', 'Code': 'AR'}
{'Name': 'Armenia', 'Code': 'AM'}
{'Name': 'Aruba', 'Code': 'AW'}
{'Name': 'Australia', 'Code': 'AU'}
{'Name': 'Austria', 'Code': 'AT'}
{'Name': 'Azerbaijan', 'Code': 'AZ'}
{'Name': 'Bahamas', 'Code': 'BS'}
{'Name': 'Bahrain', 'Code': 'BH'}
{'Name': 'Bangladesh', 'Code': 'BD'}
{'Name': 'Barbados', 'Code': 'BB'}
{'Name': 'Belarus', 'Code': 'BY'}
{'Name': 'Belgium', 'Code': 'BE'}
{'Name': 'Belize', 'Code': 'BZ'}
{'Name': 'Benin', 'Code': 'BJ'}
{'Name': 'Bermuda', 'Code': 'BM'}
{'Name': 'Bhutan', 'Code': 'BT'}
{'Name': 'Bolivia, Plurinational State of', 'Code': 'BO'}
{'Name': 'Bonaire, Sint Eustatius and Saba', 'Code': 'BQ'}
{'Name': 'Bosnia and Herzegovina', 'Code': 'BA'}
{'Name': 'Botswana', 'Code': 'BW'}
{'Name': 'Bouvet Island', 'Code': 'BV'}
{'Name': 'Brazil', 'Code': 'BR'}
{'Name': 'British Indian Ocean Territory', 'Code': 'IO'}
{'Name': 'Brunei Darussalam', 'Code': 'BN'}
{'Name': 'Bulgaria', 'Code': 'BG'}
{'Name': 'Burkina Faso', 'Code': 'BF'}
{'Name': 'Burundi', 'Code': 'BI'}
{'Name': 'Cambodia', 'Code': 'KH'}
{'Name': 'Cameroon', 'Code': 'CM'}
{'Name': 'Canada', 'Code': 'CA'}
{'Name': 'Cape Verde', 'Code': 'CV'}
{'Name': 'Cayman Islands', 'Code': 'KY'}
{'Name': 'Central African Republic', 'Code': 'CF'}
{'Name': 'Chad', 'Code': 'TD'}
{'Name': 'Chile', 'Code': 'CL'}
{'Name': 'China', 'Code': 'CN'}
{'Name': 'Christmas Island', 'Code': 'CX'}
{'Name': 'Cocos (Keeling) Islands', 'Code': 'CC'}
{'Name': 'Colombia', 'Code': 'CO'}
{'Name': 'Comoros', 'Code': 'KM'}
{'Name': 'Congo', 'Code': 'CG'}
{'Name': 'Congo, the Democratic Republic of the', 'Code': 'CD'}
{'Name': 'Cook Islands', 'Code': 'CK'}
{'Name': 'Costa Rica', 'Code': 'CR'}
{'Name': "C척te d'Ivoire", 'Code': 'CI'}
{'Name': 'Croatia', 'Code': 'HR'}
{'Name': 'Cuba', 'Code': 'CU'}
{'Name': 'Cura챌ao', 'Code': 'CW'}
{'Name': 'Cyprus', 'Code': 'CY'}
{'Name': 'Czech Republic', 'Code': 'CZ'}
{'Name': 'Denmark', 'Code': 'DK'}
{'Name': 'Djibouti', 'Code': 'DJ'}
{'Name': 'Dominica', 'Code': 'DM'}
{'Name': 'Dominican Republic', 'Code': 'DO'}
{'Name': 'Ecuador', 'Code': 'EC'}
{'Name': 'Egypt', 'Code': 'EG'}
{'Name': 'El Salvador', 'Code': 'SV'}
{'Name': 'Equatorial Guinea', 'Code': 'GQ'}
{'Name': 'Eritrea', 'Code': 'ER'}
{'Name': 'Estonia', 'Code': 'EE'}
{'Name': 'Ethiopia', 'Code': 'ET'}
{'Name': 'Falkland Islands (Malvinas)', 'Code': 'FK'}
{'Name': 'Faroe Islands', 'Code': 'FO'}
{'Name': 'Fiji', 'Code': 'FJ'}

좀더 세련되게 출력해보자.
딕셔너리의 키와 벨류를 각각 반환하는 items() 사용

import csv
with open('./resource/test1.csv', 'r') as f:
    reader = csv.DictReader(f)
    # 확인
    print(reader)   
    print(type(reader))
    print(dir(reader))
    print()
	for c in reader: 
        for k,v in c.items():
            print(k,v)
        print('---------')
    print()
>>> <csv.DictReader object at 0x00000241E7AE9E50>
>>> <class 'csv.DictReader'>
>>> ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_fieldnames', 'dialect', 'fieldnames', 'line_num', 'reader', 'restkey', 'restval']
>>> 
Name Afghanistan
Code AF
---------
Name 횇land Islands
Code AX
---------
Name Albania
Code AL
---------
Name Algeria
Code DZ
---------
Name American Samoa
Code AS
---------
Name Andorra
Code AD
---------
Name Angola
Code AO
---------
Name Anguilla
Code AI
---------
Name Antarctica
Code AQ
---------
Name Antigua and Barbuda
Code AG
---------
Name Argentina
Code AR
---------
Name Armenia
Code AM
---------
Name Aruba
Code AW
---------
Name Australia
Code AU
---------
Name Austria
Code AT
---------
Name Azerbaijan
Code AZ
---------
Name Bahamas
Code BS
---------
Name Bahrain
Code BH
---------
Name Bangladesh
Code BD
---------
Name Barbados
Code BB
---------
Name Belarus
Code BY
---------
Name Belgium
Code BE
---------
Name Belize
Code BZ
---------
Name Benin
Code BJ
---------
Name Bermuda
Code BM
---------
Name Bhutan
Code BT
---------
Name Bolivia, Plurinational State of
Code BO
---------
Name Bonaire, Sint Eustatius and Saba
Code BQ
---------
Name Bosnia and Herzegovina
Code BA
---------
Name Botswana
Code BW
---------
Name Bouvet Island
Code BV
---------
Name Brazil
Code BR
---------
Name British Indian Ocean Territory
Code IO
---------
Name Brunei Darussalam
Code BN
---------
Name Bulgaria
Code BG

예제를 통해 쓰는 방법도 알아보겠습니다.

예4

먼저 중첩 리스트를 만들겠습니다.
리스트안에 7개의 리스트가 있고, 각각의 리스트 안에는 3개의 값이 들어 있습니다.

import csv
w = [[1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15], [16,17,18], [19,20,21]]
with open('./resource/write1.csv', 'w', newline='', encoding='UTF-8') as f: # 현재경로에서 상대경로로
    print(dir(csv))
    wt = csv.writer(f) # wt는 파일과 연동되서 쓰기 직전의 준비상태
>>>
['Dialect', 'DictReader', 'DictWriter', 'Error', 'QUOTE_ALL', 'QUOTE_MINIMAL', 'QUOTE_NONE', 'QUOTE_NONNUMERIC', 'Sniffer', 'StringIO', '_Dialect', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', 'excel', 'excel_tab', 'field_size_limit', 'get_dialect', 'list_dialects', 're', 'reader', 'register_dialect', 'unix_dialect', 'unregister_dialect', 'writer']
import csv
w = [[1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15], [16,17,18], [19,20,21]]
with open('./resource/write1.csv', 'w', newline='', encoding='UTF-8') as f: 
    wt = csv.writer(f) 
    for v in w: # 한줄씩 쓰기 때문에 v로 쓰는것, [1,2,3] 들을 하나의 record로 생각한다.
        wt.writerow(v) # writerow라는 메소드로 한총 for문은 7번 반복
>>>
1,2,3
4,5,6
7,8,9
10,11,12
13,14,15
16,17,18
19,20,21

열과 행에서 콤마로 구분된 로우 단위로 작성이 됩니다.
하나의 단위 리스트가 레코드이며, 그 안에 우리가 구분하는 요소는 콤마로 기본값이 구분이 되어 작성됩니다.

예4

마지막으로 딕셔너리의 키값을 필드명으로 활용해서 써보는 예제를 해봅시다.
DictWriter로 작성
우리가 만든 fields를 fieldnames라는 인수로 지정을 해주면 One,Two,Three가 자동으로 fieldname으로 들어갑니다.

w= [[1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15], [16,17,18], [19,20,21]]
with open('./resource/write2.csv', 'w', newline='' , encoding='UTF-8') as f: # 현재경로에서 상대경로로
    # 필드명    
    fields = ['One', 'Two', 'Three']
    # Dic Writer
    wt = csv.DictWriter(f, fieldnames=fields)
    # Header Writer
    wt.writeheader() # Header이름이 내부적으로 작성된 상태
    for v in w:
        wt.writerow({'One' :v[0], 'Two' :v [1], 'Three' : v[2]}) # 위의 fields와 값을 정확하게 mapping 한다.
>>>>
One,Two,Three
1,2,3
4,5,6
7,8,9
10,11,12
13,14,15
16,17,18
19,20,21

기본적인 파이썬 문법과정을 모두 배웠습니다. 다음에는 지금까지 배운 것들을 가지고 간단한 프로젝트를 해보겠습니다.🙂

출처 : 인프런

profile
ice blue

0개의 댓글