1.  API 통해 위치 정보 얻기

import urllib.request as request
import json
import datetime

# API 이용하기
# openweathermap.org

api_key: str = 'd1569da48f0b4251e9ec538982a29548'

# 대구 위치 정보 얻기
# https://openweathermap.org/api/geocoding-api

city: str = 'Taegu'
url: str = f'http://api.openweathermap.org/geo/1.0/direct?q={city}&limit=5&appid={api_key}'
print(url)

json_data = request.urlopen(url).read()
dict_data = json.loads(json_data)
lat = dict_data[0]['lat']
lon = dict_data[0]['lon']
print(f'{lat} / {lon}')

# 현재 날씨
# https://openweathermap.org/current
# lang=kr : 한국어 사용
# units=metric : 섭씨온도

url = (f'https://api.openweathermap.org/data/2.5/weather?lat={lat}&'  #위도
       f'lon={lon}&'  #경도
       f'appid={api_key}&'
       f'lang=kr&'
       f'units=metric')
print(url)
json_data = request.urlopen(url).read()
dict_data = json.loads(json_data)
json_data = json.dumps(dict_data, indent=4)
# print(json_data)

print(f'도시 : {dict_data["name"]}')
print(f'현재날씨 : {dict_data["weather"][0]["description"]}')
print(f'최고기온 : {dict_data["main"]["temp_max"]}')
print(f'최저기온 : {dict_data["main"]["temp_min"]}')
print(f'일출시간 : {datetime.datetime.fromtimestamp(dict_data["sys"]["sunrise"])}')
print(f'일몰시간 : {datetime.datetime.fromtimestamp(dict_data["sys"]["sunset"])}')

# 날씨 예보 : 5days / 3 hours
# https://openweathermap.org/forecast5

url: str = (f'https://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={api_key}&lang=kr&'
       f'units=metric')
print(url)

json_data = request.urlopen(url).read()
dict_data = json.loads(json_data)
json_data = json.dumps(dict_data, indent=4)
print(json_data)

weather_list = dict_data['list']  #json 데이터 중에서 list key에 해당하는 목록 가져오기.
#print(weather_list)

for item in weather_list:
       print(f'시간: {datetime.datetime.fromtimestamp(item["dt"])}', end=', ')
       print(f'최고기온: {item["main"]["temp_max"]}', end=', ')
       print(f'날씨: {item["weather"][0]["main"]}', end=', ')
       print(f'날씨: {item["weather"][0]["description"]}')
       print()

 

print(url) 을 실행했을 때 나온 주소창으로 들어가면 나오는 데이터

 

실행결과

 


 

2. 공공데이터를 JSON 타입으로 받아 필요한 내용 출력하고  CSV 타입으로 저장

 

# 공공데이터 포탈에서 '대구광역시_맛집' 검색 (키사용이 없음)
# https://www.data.go.kr/data/15057236/openapi.do
# 중구의 맛집 목록을 json 타입으로 받아서 처리

# 1. 음식카테고리 출력
# {'한식', '일식', '세계요리', '중식', '전통차/커피전문점', '특별한 술집', '디저트/베이커리', '양식'}

# 2. 일식의 음식점명, 연락처, 메뉴 출력
# --------------------
# 음식점명: 종로초밥
# 연락처: 053-252-0321
# 메뉴: 광어회 50,000원 <br />모둠회 40,000원 <br />무침회 20,000원<br />
# --------------------
# 음식점명: 삼삼구이초밥
# 연락처: 053-425-3392
# 메뉴: 회덮밥 9,000원 <br />미주구리 30,000원 <br />점심특선 6,000원<br />
# --------------------
import json
import urllib.request as request


url: str = "https://www.daegufood.go.kr/kor/api/tasty.html?mode=json&addr=%EC%A4%91%EA%B5%AC"

json_data = request.urlopen(url).read()
dict_data: dict = json.loads(json_data)
# print(dict_data)

# 문제 1)
food_kind = set()  # 중복 값 걸러주는 set 활용
for row in dict_data['data']:
    food_kind.add(row['FD_CS'])
print(food_kind)


# 문제 2)
for item in dict_data['data']:
    kind = item['FD_CS']
    if kind == "일식":
        print(f'음식점명: {item["BZ_NM"]}')
        print(f'연락처: {item["TLNO"]}')
        print(f'메뉴: {item["MNU"]}')
        print("-" * 20)

# 3. csv 파일 저장
# 파일명 : daegu_food_jonggu_list.csv
# 인코딩 : utf-8
# 헤더 : '음식 카테고리', '음식점명', '연락처', '메뉴'
import csv

food_list: list[dict] = list()
name_list: list[str] = ['음식 카테고리', '음식점명', '연락처', '메뉴']  
# csv 헤더 및 딕셔너리의 key값으로 사용.

for data in dict_data['data']:
    if data['FD_CS'] == '일식':
        new_data: dict = dict()
        new_data[name_list[0]] = data['FD_CS']
        new_data[name_list[1]] = row["BZ_NM"]
        new_data[name_list[2]] = row["TLNO"]
        new_data[name_list[3]] = row["MNU"]

        food_list.append(new_data)

file_name = 'daegu_food_jonggu_list.csv'
with open(f'../output_02/{file_name}', 'w', newline='', encoding='UTF-8') as csvfile:
    writer = csv.DictWriter(csvfile, name_list)
    writer.writeheader()
    for data in food_list:
        data: dict
        writer.writerow(data)

print(f'{file_name} 파일이 생성되었습니다.')

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 자료 ]

 


 

1. 서버에서 데이터 받기

 

1) 아이디와 이름 순서대로 데이터를 전달
 

    🚀  test, tom  ➡️ 인덱스를 사용하는 것처럼 위치값으로 파악
    🚀  빈값이나, 값에 구분자가 들어가는 경우 어려움등의 문제로 사용 빈도 낮음

 


2) xml 방식

 

    🚀  <id>test</id>
          <name>tom</name>
           ➡️  마크업 방식, 속성값이 반복되어서 상대적으로 데이터의 크기가 커짐

 


3) json 방식

 

    🚀  'id': 'test',
           'name': 'tom'
            ➡️  객체 속성 표현 방식. 상대적으로 간결한 표현

 


 

2.  JSON 파일 입출력

 

 1) JSON 파일이란?

 

    👾  JavaScript Object Notation의 약자로 JavaScript의 객체 표현 방법이라는 뜻

    👾  데이터를 전달할 때 사람이 읽고 쓰기 쉽도록 텍스트 형식을 정해 놓은 개방형 데이터 표준 형식
    👾  많은 양의 데이터를 처리할 때는 속도가 느린 단점이 있으므로 경량의 데이터를 주고 받을 때 주로 사용
 


 2) JSON 데이터 형식


    👾  속성 attribute - 값 value 쌍으로 구성된 데이터들이 순서없이 모여 있는 구조
          ⚡️ 중괄호를 이용해서 전체 JSON 데이터를 묶어 주고 속성과 값 사이에 콜론(:)을 붙여 줌
          ⚡️ 속성과 값으로 구성된 각 데이터의 구분은 쉼표(,)를 이용
                ∴  즉, 파이썬의 딕셔너리와 같은 모습

 



3) JSON 파일 생성


    👾  JSON 데이터 처리를 위해서 json 모듈 제공
         ⚡️  json 모듈을 import 하면 리스트나 딕셔너리와 같은 파이썬 객체를 JSON 데이터로 변환하거나,
              JSON 데이터를 다시 파이썬 객체로 변환할 수 있음

    👾  JSON 인코딩 encoding : 파이썬 객체를 JSON 문자열로 변환하는 것
         ⚡️ 변환된 문자열을 파일에 기록하면 확장자가 json인 JSON 파일 (*.json)을 만들 수 있음
         ⚡️ json.dumps() 메소드를 이용해서 JSON 인코딩을 처리할 수 있음

# json 모듈 import
import json

dict_list = [
    {
        'name': 'james',
        'age': 20,
        'spec': [
            175.5,
            70.5
        ]
    },
    {
        'name': 'alice',
        'age': 21,
        'spec': [
            168.5,
            60.5
        ]
    }
]

# 인코딩 메소드를 이용해 json 문자열로 변환
json_string: str = json.dumps(dict_list)
print(json_string)
'''
실행결과)
[{"name": "james", "age": 20, "spec": [175.5, 70.5]}, 
 {"name": "alice", "age": 21, "spec": [168.5, 60.5]}]
'''

# output_02 디렉토리에 json 파일 생성
with open('../output_02/dict_list_01.json', 'w') as file:
    file.write(json_string)

print('dict_list_01.json 파일이 생성되었습니다.')

 


(1) indent 옵션

 

📌  JSON 데이터는 네트워크를 주고받는 데이터의 표준 형식
📌  파일의 크기를 줄이기 위해서 의도적으로 불필요한 공백 문자 white space가 제거된 상태로 만들어 지기 때문에 

      사람들이 직접 그 내용을 해석하기에는 불편

 

    ⚡️ 보기 좋은 형식으로 만들기 위해서 json.dump() 메소드에 indent 옵션을 추가 할 수 있음
           ➡️  indent 옵션을 추가하면 JSON 데이터에 들여쓰기와 줄 바꿈이 추가되면서 보기 좋은 형식으로 만들어짐

json_string = json.dumps(dict_list, indent=4)  # indent 옵션 사용

with open('../output_02/dict_list_02.json', 'w') as file:
    file.write(json_string)

print('dict_list_02.json 파일이 생성되었습니다.')

 

 

📁  indent = 4는 들여쓰기로 공백문자 4개로 처리 한다는 의미
📁  하지만 indent 옵션을 사용하면 파일의 크기가 커지기 때문에 네트워크 전송이 목적이라면 사용하지 않는 것이 좋음
📁 JSON 데이터는 문자열을 큰따옴표로 묶어서 처리

 

 

 

 

 

 

 

 


 

 4) JSON 파일 읽기


    👾  JSON 디코딩 decording : 인코딩된 JSON 데이터를 다시 파이썬 객체로 변경하는 것
    👾  디코딩을 처리하는 메소드는 json.loads()

with open('../output_02/dict_list_02.json', 'r') as file:
    json_reader = file.read()
    dict_list = json.loads(json_reader)
    print(dict_list)
    # [{'name': 'james', 'age': 20, 'spec': [175.5, 70.5]}, 
    # {'name': 'alice', 'age': 21, 'spec': [168.5, 60.5]}]
    print(type(dict_list))  # <class 'list'>

 

    📁  json 파일을 read() 메소드로 한 번에 전체를 읽어 들여 json_reader에 저장
    📁  json.loads(json_reader)를 통해서 디코딩이 이뤄지면 파이썬 객체인 dict_list가 생성
    📁  dict_list는 리스트 내부에 2개의 딕셔너리가 저장된 구조이기 때문에 for 문을 이용해서 그 내용을 모두 처리 가능

 


 

3. JSON과 API

🚀  JSON은 데이터를 사람이 읽을 수 있는 문자열(바이너리가 아니라 텍스트)로 나타내는 방식 
🚀  많은 웹 사이트에서 프로그램이 웹 사이트와 상호 작용하는 데 JSON 형식의 내용을 제공
        ➡️  이를 API 제공이라고 하고, API로 접근하는 것은 URL을 통해 일반 웹 페이지에 접근하는 것과 동일
        ➡️  차이점API가 반환하는 값은 기계를 위한 JSON 형식으로 되어 있음

🚀  원하는 데이터를 얻으려면 프로그램이 요청해야 할 URL 뿐만 아니라 반환되는 JSON 데이터 구조의 일반적인 형식에 대한 문서도 찾아 봐야 되는데, API를 제공하는 모든 사이트는 이 문서를 제공

 


 

1) JSON 모듈


👾  JSON 모듈은 json.loads(), json.dumps() 함수로 JSON 데이터와 파이썬 값을 서로 변환하는 모든 세부 사항을 처리
👾  JSON문자열, 정수, 부동 소수점 수, 불, 리스트(배열) '[]', 딕셔너리(객체) '{}', NoneType 자료형 값만 저장 가능

import json

 


 

2) loads() 함수를 사용하여 JSON 읽기


👾  JSON 데이터가 들어 있는 문자열을 파이썬 값으로 변환하려면, 이를 json.loads() 함수에 전달
👾  JSON 문자열은 큰 따옴표를 사용

string_json_data: str = '{"name": "Zopgie", "isCat": true, "miceCaught": 0, "felineIQ": null}'
json_data_as_python_value = json.loads(string_json_data)
print(type(json_data_as_python_value))  # <class 'dict'>
print(json_data_as_python_value)
# {'name': 'Zopgie', 'isCat': True, 'miceCaught': 0, 'felineIQ': None}

 

# 온라인에서 JSON 파일 열기
import urllib.request as request

# urlopen() 함수 사용하여 소스 가져옴
json_data = request.urlopen("https://jsonplaceholder.typicode.com/todos/1").read()
print(type(json_data))  # <class 'bytes'>

# loads() 함수로 파이썬 객체로 변환
python_data = json.loads(json_data)
print(type(python_data))  # <class 'dict'>
print(python_data)  
#{'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}

   

    📌  urllib.request : 내부모듈(url 라이브러리). 기본적인 기능만 제공
    📌  requests : 외부모듈. 다양한 기능을 제공. 실작업에 많이 사용

 


 

3) dupms() 함수를 이용하여 JSON 작성하기


👾  파이썬 값을 JSON 형식 데이터 문자열로 변환

python_data: dict = {'name': 'Zopgie', 'isCat': True, 'miceCaught': 0, 'felineIQ': None}
json_data: str = json.dumps(python_data)
print(type(json_data))  # <class 'str'>
print(json_data)  
# {"name": "Zopgie", "isCat": true, "miceCaught": 0, "felineIQ": null}

 

    📌  JSON 에서는 True ▶️ true,  None ▶️ null 로 표현

 

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 자료 ]


 

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

 

 

 


 

1. mutable & immutable

👩🏻‍💻  mutable : 생성된 후에도 변경이 가능한 자료형 

        ex. list, set, dict

👩🏻‍💻 immutable : 생성된 후에는 변경이 불가능한 자료형 

        ex. int, float, str, tuple

# mutable
# 할당받는 메모리에 저장된 값을 다른 값으로 바꿀 수 있음
# id() : 객체의 고유값 반환. 메모리 주소를 구별하기 위한 용도로 사용
me = [1, 2, 3]
print(id(me)) # 4370596288
me.append(4)
print(id(me)) # 4370596288 / 할당된 메모리 주소는 변경이 되지 않음

# immutable
# 한 번 생성하면 최초로 저장된 값을 다른 값으로 바꿀 수 없음
obj = 10
print(id(obj)) # 4343431696
obj = obj + 1
print(obj) # 11
print(id(obj)) # 4343431728 / 할당된 메모리 주소가 변경이 됨
# 메모리에 저장된 데이터를 수정하는 것이 아니라, 새로 할당을 받아서 데이터를 저장

 


 

2. % 연산자

      %s : string 

      %f : float

      %d : decimal (십진법)
name = 'Kai'
print('내 이름은 %s 입니다.' % name) # 내 이름은 Kai 입니다. 
print('내 이름은 ', name, '입니다.', sep='')
print('내 이름은 ' + name + '입니다.')

height = 120.5
print('내 키는 %fcm입니다.' % height)  # 내 키는 120.500000cm입니다. 

weight = 23.55
print('내 몸무게는 %.1fkg입니다.' % weight)  # 내 몸무게는 23.6kg입니다.

year, month, day = 2014, 8, 25
print('내 생일은 %d년 %d월 %d일 입니다.' % (year, month, day))
# 내 생일은 2014년 8월 25일 입니다.

 


 

3. 삼항 조건 연산자

👩🏻‍💻  일반적인 삼항 조건 연산자 : 조건식 ? 참 : 거짓
👩🏻‍💻  파이썬 삼항 조건 연산자 : 참 if 조건식 else 거짓

a = 10
b = 20
result = (a - b) if (a >= b) else (b - a)
print('{}과 {}의 차이는 {}입니다.'.format(a, b, result)) # 10과 20의 차이는 10입니다.

 

4. 지역변수/전역변수

1) 지역 변수 local variable

 

  📁  함수 내부에서 선언한 변수는 함수 내부에서만 사용.  함수 외부에서는 지역변수에 접근할 수 없음

def f():
    a = 10
    print(f'f()내부 : {a}')

f()  # f() 내부 : 10
# print(f'f() 외부 : {a}')  # 함수 외부에서는 a 변수를 사용할 수 없음

 


 

2)  전역변수 global variable


📁 함수 외부에서 선언한 변수는 함수 내부나 함수 외부에서 모두 사용할 수 있음

def f():
    print(f'f() 내부 : {b}')  

b = 10 # 전역변수
f() # f() 내부 10
print(f'f() 외부 : {b}')  # f() 외부10

# 1) 전역변수를 단순히 참조만 하는 경우 -> 읽기만 하는 경우
a = 0
def f():
    print(a)  # 함수 f() 내부에서 전역변수 a를 참조

f()  # 0
print(a)  # 0 / 함수 f() 외부에서 전역변수 a를 참조


# 2) 전역변수의 값을 변경하는 경우
a = 0

def f():
    global a  # 전역변수 a를 사용
    a = 10  # 전역변수 a의 값을 변경

f()  # 함수 f() 실행
print(a)  # 10 / 전역변수의 변경된 값을 확인

 

 

 

 

 

[ 내용 참고 :  IT 학원 강의 ]


 

1. 파일

📁  변수는 프로그램을 실행할 때 데이터를 저장하기 좋은 방법
        ➡️  그러나 프로그램을 종료한 후에도 데이터를 유지하고 싶다면, 파일 형태로 저장해야 함

 

1) 파일과 파일 경로

 

   ⚡️  파일에는 파일 이름과 경로라는 두 가지 주요속성이 있다.
          ex. 윈도우 운영체제를 사용하는 노트북 컴퓨터의 C:\Users\al\Documents 라는 경로에

                 project.docx 라는 이름의 파일이 있는 경우
                  ▶️  파일이름 project.docx는 워드 문서이고 Users, al, Documents는 모두 폴더(디렉토리)
                  ▶️  폴더 안에는 파일이나 다른 폴더가 들어 있을 수 있음

   ⚡️ 경로의 C:\는 루트 폴더를 나타내며 모든 폴더가 이 안에 들어 있음
          📌  윈도우에서 루트 폴더의 이름은 "C:\"이며, C 드라이브라고 부름.
          📌  맥os나 리눅스에서 루트 폴더는 "/"
          📌  윈도우, 맥os에서는 폴더이름이나 파일이름의 대소문자를 구분하지 않지만, 리눅스의 경우 이를 구분함

   ⚡️ 윈도우에서의 폴더 구분은 "\" 백슬러시를 사용하고, 맥 os나 리눅스에서는 "/" 슬러시를 사용함.

# 1) Path 객체 사용.
from pathlib import Path
path = Path('spam', 'bacon', 'eggs')  # 운영체제에 맞는 경로 체제를 만들어 줌.
print(path)  # spam/bacon/eggs

# 2) platform.system() 함수 사용.
import platform
my_os = platform.system()
print("OS in my system: ", my_os)  # OS in my system:  Darwin
if my_os == 'Darwin':
    print('Mac 운영체제 입니다.')
else:
    print('Mac 운영체제가 아닙니다.')
# 현재 작업 디렉토리
print(Path.cwd())  # /Users/Desktop/pycharm/pythonProject/part2

 

2) 절대 경로와 상대 경로


⚡️ 절대 경로 : 항상 루트 폴더에서 시작하는 경로
⚡️ 상대 경로 : 현재 작업 디렉토리에 대한 경로 
     📌  '.' : 현재 디렉토리
    📌  '..' : 상위 디렉토리


 

3) 새로운 디렉토리 만들기

 

⚡️ os.makedirs() 함수로 새로운 디렉토리를 만들 수 있음
⚡️ os.path.isdir(path) : path 인자의 디렉토리가 있는지 확인

import os
path = './test'
if not os.path.isdir(path):
    os.makedirs(path)  # 현재 작업 폴더 안에 test라는 폴더 생성.

 

4) 파일 크기와 폴더 내용 확인

 

⚡️ os.path.getsize(path) : path 인자에 해당하는 파일 크기 반환
⚡️ os.listdir(path) : path에 있는 파일 이름 리스트를 반환

path = './input'
print(os.path.getsize(f'{path}/hello.txt'))  # 53
list_dirs = os.listdir(path)
print(list_dirs)  # ['연락처.txt', 'hello.txt', '엄마돼지아기돼지.txt']

 


 

2. 파일 열기

📁  입출력 파일을 지정하는것을 의미 ( 파일 객체 생성 )
📁  파일 입력과 파일 출력 모두 반드시 파일 열기 작업을 가장 먼저 수행

파일객체 = open(파일명, 모드)


1) 파일명

🚀  입출력 작업을 수행할 파일을 의미
🚀  파일명만 작성할 수도 있고 경로를 함께 작성할 수도 있음

# 파일명만 작성하는 경우 : 파이썬 소스 파일과 같은 경로에 존재하는 경우
open('sample.txt')

# 전체 경로를 작성하는 경우 : 빈도가 적음.
open('C:/sample.txt')

# 현재 디렉터리(.)를 기준으로 경로를 결정
open('./sample.txt')
open('./input/hello.txt')

# 상위 디렉터리(..)를 기준으로 경로를 결정
open('../sample.txt')

2) 모드

r (read) 읽기
w (write) 쓰기 (새로 쓰기 모드)
a (append) 추가 (뒤에 이어서 쓰기 모드)
x (exclusive) 배타적 추가 (파일 있으면 오류, 없으면 새로 생성)


🚀  파일의 종류
     - t (text) 텍스트 파일 : 메모장으로 열 수 있는 파일
     - b (binary) 바이너리 파일 (텍스트 파일 외의 모든 파일)


 

3. 파일 닫기

👾  파일을 더 이상 사용하지 않거나 프로그램을 종료하고자 할 때

파일객체.close()

 


 

4. 파일 생성

file = open('./output/my_file.txt', 'wt')  # 빈파일 생성
print('my_file.txt 파일이 생성되었습니다.')
file.close()

# 텍스트 파일을 새로 만들 수 있는 모드인 wt 모드를 사용하여 my_file.txt라는 이름의
# 텍스트 파일을 output 이라는 디렉토리에 생성하는 코드

🚀   with문
    -  close() 메소드를 자동으로 호출할 수 있는 문법을 제공
    -  with문을 사용하면 with문이 끝날 때 언제나 close() 메소드가 자동으로 호출

         ➡️  별도의 예외 처리를 하지 않더라도 프로그램이나 파일의 에러로 close()가 호출이 안되는 상황을 방지

# 기본 구성
with open (파일명, 모드) as 파일객체:
    파일처리코드
with open('./output/my_file_1.txt', 'wt') as file:
    print('my_file_1.txt 파일이 생성되었습니다.')

 

5.  파일 입출력

📁  파일 입출력 : 컴퓨터에 저장된 파일을 읽어 들이는 것은 물론 파일을 생성해서 컴퓨터에 저장하는 것도 가능
    📌 파일 입력 input : 기존의 파일 내용을 읽어 들이는 것
    📌 파일 출력 output : 기존 파일에 새로운 내용을 추가하거나 새로운 파일을 생성하는 것

 

1) 파일 출력 output

# 1. 텍스트 파일 생성하기
file = open('./output/hello.txt', 'wt')

# hello.txt에 글 쓰기.
file.write('안녕하세요.')
file.write('\n')  # 줄 바꿈
file.write('반갑습니다.')
file.write('\n')
print('hello.txt 파일이 생성되었습니다.')  # 진행 상황을 알기 위해서 화면 출력.

file.close()

# 2. 텍스트 파일에 내용 추가하기
# 기존 파일에 내용을 추가할 수 있는 모드는 a 모드
file = open('./output/hello.txt', 'at')

file.write('Hello.\n')
file.write('Nice to meet you.\n')
print('hello.txt 파일에 새로운 내용이 추가되었습니다.')

file.close()

 


2) 파일 입력  input

1)  read() 메소드

📁  파일로부터 데이터를 읽어 들이는 메소드
📁  텍스트 모드와 바이너리 모드에서 다른 방식으로 동작

file.read(size)


    👾  반환값 : 텍스트 모드 - 읽어 들인 문자열, 바이너리 모드 - 읽어 들인 바이트열
    👾  매개변수 size : 텍스트 모드- 읽어 들일 최대 문자의 개수, 바이너리 모드- 읽어 들일 최대 바이트 수
    👾  매개변수 size 생략 : 파일 전체 읽음
    👾  파일의 끝에 도달 : 빈 문자열 ('') 반환

file = open('./input/hello.txt', 'rt', encoding='cp949')

str = file.read()  # 파일 전체를 한 번에 읽어 들임
print(str, end='')

file.close()

 

    💡 'encoding = cp949' 는 맥 os 에서 파일 처리할 때 사용


2)  readline() 메소드

📁  텍스트 파일을 한 줄씩 읽어서 처리하는 메소드
📁  파일이 종료되어 더 이상 읽어 들일 글자가 없으면 빈 문자열('')을 읽어 들임
📁  반복문을 이용해서 여러 번 읽어 들어야 파일 전체를 읽어 들일 수 있음

file = open('./input/hello.txt', 'rt', encoding='cp949')

while True:
    str = file.readline()
    if str == '':
        break
    print(str, end='')

file.close()

3) readlines() 메소드

📁  라인 line 하나가 아니라 전체 라인 lines을 모두 읽어 각 라인 line 단위로 리스트에 저장하는 메소드

file = open('input/hello.txt', 'rt', encoding='cp949')

line_list = file.readlines()
print(line_list) # ['안녕하세요.\n', '반갑습니다.\n', 'Hello.\n', 'Nice to meet you.\n']
for line in line_list:
    print(line, end='')

file.close()

# enumrate() 함수를 이용하면 라인 번호 line number 도 함께 출력할 수 있다
file = open('input/hello.txt', 'rt', encoding='cp949')

line_list = file.readlines()
for no, line in enumerate(line_list):
    print('{} {}'.format(no + 1, line), end='')

file.close()

# sys 모듈을 이용하면 보다 쉽게 파일을 읽을 수 있다
# sys 모듈에는 표준 입출력을 위한 stdin과 stdout 객체가 포함
# stdout은 출력을 위한 객체이며 화면 출력 메소드인 write()와 writelines() 메소드를 사용할 수 있음
# writelines() 메소드를 사용하면 리스트와 같은 반복 가능한 객체의 각 요소를 한 줄씩 자동으로 출력

import sys

file = open('input/hello.txt', 'rt', encoding='cp949')

line_list = file.readlines()
sys.stdout.writelines(line_list)

file.close()

 


 

6. pickle

📁  텍스트가 아닌 자료형 (리스트나 딕셔너리 자료형등)을 저장하기 위한 방식
📁  import pickle을 통하여 모듈 임포트가 필요
📁  pickle로 데이터를 저장하거나 불러올때는 파일을 바이너리 형식으로 읽거나 써야함 (wb, rb)
📁  모든 파이썬 데이터 객체를 저장하고 읽을 수 있음

import pickle
data = {
    'a': [1, 2.0, 3, 4 + 6j],
    'b': ("character string", "byte string"),
    'c': {None, True, False}
}
print(type(data))  # <class 'dict>

# 1. 일반 텍스트 파일 형식을 사용하는 경우.
# 저장
with open('./output/data.txt', 'w') as file:
    # file.write(data)  # TypeError: write() argument must be str, not dict
    file.write(str(data))  # write() 메서드의 인자는 문자열이어야 함.

# 읽기
with open('./output/data.txt', 'r') as file:
    data_output = file.read()
print(data_output)  
# {'a': [1, 2.0, 3, (4+6j)], 'b': ('character string', 'byte string'), 
# 'c': {False, True, None}}
print(type(data_output))  #  <class 'str'>

# 2. pickle 방식을 사용하는 경우
# 저장
with open('./output/data.my_pickle', 'wb') as file:
    pickle.dump(data, file)

# 읽기
with open('./output/data.my_pickle', 'rb') as file:
    data_output = pickle.load(file)  # 읽음.

print(data_output)  
# {'a': [1, 2.0, 3, (4+6j)], 'b': ('character string', 'byte string'), 
# 'c': {False, True, None}}
print(type(data_output))  # <class 'dict'>
print(data_output.get('a'))  # [1, 2.0, 3, (4+6j)]

 

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]


 

1. 클래스 변수

🚀  클래스를 구현할 때 인스턴스마다 서로 다른 값을 가지는 경우에는 인스턴스 변수를 사용
🚀  모든 인스턴스 변수들은 self 키워드를 붙여서 사용
🚀  모든 인스턴스가 동일한 값을 사용할 때는 클래스 변수로 처리해서 모든 인스턴스들이 공유하도록 처리하는 것이 좋음
        ➡️  하나의 값을 모든 인스턴스가 공유하기 때문에 메모리 공간의 낭비를 막을 수 있음

     ⚡️  self
         - 관례적으로 모든 메서드의 첫 번째 매개변수 이름을 self로 지정.
         - self라는 명칭은 관례적으로 사용하는 단어.

# 클래스 변수 만들기
class 클래스 이름:
    클래스 변수 = 값
# 클래스 변수 접근
클래스 이름.변수 이름
class Korean:
    country = '한국'  # 클래스 변수 country

    def __init__(self, name, age, address):
        self.name = name  # 인스턴스 변수
        self.age = age
        self.address = address

print(Korean.country)  # 객체 생성전에도 사용 가능.

man = Korean('홍길동', 35, '서울')
print(man.name)
# print(Korean.name)  # AttributeError: type object 'Korean' has no attribute 'name'

print(man.country)  # 인스턴스 man을 통한 클래스 변수 접근
print(Korean.country)  # 클래스 Korean을 통한 클래스 변수 접근

print('객체 property 생성과 동일한 이름의 클래스 변수')
man.country = '중국'  # 객체의 인스턴스 변수 생성
print(man.country)  # 중국. 
# 클래스 변수가 아니라 인스턴스 변수를 불러옴. 
# man 객체의 country 라는 인스턴스 변수와 country 클래스 변수
print(man.__class__.country)  # 한국. 객체를 사용해서 클래스 변수 불러오기.
print(Korean.country)  # 한국.

print('객체를 이용해서 클래스 변수 값 변경')
man.__class__.country = '영국'
print(Korean.country)  # 영국

print('클래스를 이용해서 클래스 변수 값 변경')
Korean.country = '미국'  # 클래스 변수를 변경
print(Korean.country)  # 미국

man2 = Korean('홍길동2', 35, '서울')
print(man2.country)  # 미국
print(Korean.country)  # 미국

# 클래스 변수는 클래스를 통해서 접근하는 것이 권장사항

 


 

2. 클래스 메소드

🚀  클래스 변수를 사용하는 메소드를 의미
 

   ⚡️ 주요 특징
         a. 인스턴스 혹은 클래스로 호출
         b. 생성된 인스턴스가 없어도 호출할 수 있음
         c. @classmethod 데코레이터 decorator를 표시하고 작성
         d. 매개변수 self를 사용하지 않고 cls를 사용
         e. 클래스 메소드는 self를 사용하지 않기 때문에 인스턴스 변수에 접근할 수 없지만 cls를 통해서 클래스 변수에 접근할 수 있음

class Korean:
    country = '한국'  # 클래스 변수 country

    @classmethod
    def trip(cls, country):
        if cls.country == country:
            print('국내여행입니다.')
        else:
            print('해외여행입니다.')

Korean.trip('한국')  # 국내여행입니다.
Korean.trip('미국')  # 해외여행입니다.

 


 

3. 정적 메소드

🚀  인스턴스 또는 클래스로 호출
🚀  생성된 인스턴스가 없어도 호출 가능
🚀  @staticmethod 데코레이터 decorator를 표시하고 작성
🚀  반드시 작성해야 할 매개변수가  없음

 

    ⚡️  self와 cls를 모두 사용하지 않기 때문에 인스턴스 변수와 클래스 변수를 모두 사용하지 않는 메소드를 정의하는 경우에 적절
    ⚡️  정적 메소드는 클래스에 소속이 되어 있지만, 인스턴스에는 영향을 주지 않고 또 인스턴스로부터 영향을 받지도 않음

class Korean:
    country = '한국'  # 클래스 변수 country

    @staticmethod
    def slogan():
        print('Imagine your Korea')

Korean.slogan()  # Imagine your Korea

 


 

4. 상속  inheritance

 

1) 상속이란?

👾  어떤 클래스가 가지고 있는 기능을 그대로 물려받아서 사용할 수 있는 클래스를 만들 수 있다.
👾  다른 클래스의 기능을 물려받을 때 상속받는다는 표현을 사용
👾  상속 관계에 있는 클래스를 표현할 때 '부모 클래스와 자식 클래스'라는 말을 사용

    ⚡️ 부모 클래스 : 상속해 주는 클래스 / 슈퍼 클래스 super class , 기반 클래스 base class
    ⚡️ 자식 클래스 : 상속 받는 클래스 / 서브 클래스 sub class, 파생 클래스 derived class


2) 상속 관계 구현

👾  기본적으로 두 클래스가 상속 관계에 놓이려면 IS-A 관계가 성립해야 한다
👾  IS-A 관계란 '~은 ~ 이다'로 해설할 수 있는 관계를 의미
        ex. '학생은 사람이다 Student is a Person'처럼 해석되는 것이 IS-A 관계
                이때 Student 는 서브 클래스가 되고, Person은 슈퍼 클래스가 됨

👾  has-a 관계는  '그릇이 스쿱을 갖는다 Bowl has-a Scoop'
👾  has-a 관계는 상속이 아니라 구성 Composition으로 구현함

# 상속의 기본적인 형식
class 슈퍼 클래스:
    본문

class 서브 클래스(슈퍼 클래스):
    본문


  ⚡️  서브 클래스를 구현할 때는 괄호 안에 어떤 슈퍼 클래스를 상속 받는지 명시
  ⚡️  상속 관계에 놓인 서브 클래스는 마치 자신의 것처럼 슈퍼 클래스의 기능을 사용할 수 있음

 

class Person:  # 슈퍼 클래스
    def __init__(self, name):
        self.name = name

    def eat(self, food: str) -> None:
        print(f'{self.name}가 {food}를 먹습니다.')

class Student(Person):  # 서브 클래스
    def __init__(self, name: str, school: str) -> None:
        super().__init__(name)  # 슈퍼 클래스의 생성자 실행
        self.school = school

    def study(self) -> None:
        print(f'{self.name}는 {self.school}에서 공부를 합니다.')

potter = Student('해리포터', '호그와트')
potter.eat('감자')  # 해리포터가 감자를 먹습니다.
potter.study()  # 해리포터는 호그와트에서 공부를 합니다.

 

3) 서브 클래스의  __init__()

👾  서브 클래스의 생성자를 구현할 때는 반드시 슈퍼 클래스의 생성자를 먼저 호출하는 코드를 작성해야 함
👾  super라는 키워드는 슈퍼 클래스를 의미

class Computer:  # 슈퍼 클래스
    def __init__(self):
        print('슈퍼 클래스의 생성자가 실행되었습니다.')

class NoteBook(Computer):  # 서브 클래스
    def __init__(self):
        super().__init__()
        print('서브 클래스의 생성자가 실행되었습니다.')

 


 

4) 서브 클래스의 인스턴스 자료형

👾  슈퍼 클래스 객체는 슈퍼 클래스의 인스턴스
👾  그에 비해 서브 클래스 객체는 서브 클래스의 인스턴스이면서 동시에 수퍼 클래스의 인스턴스

 

    ⚡️ 서브 클래스 Student의 객체는 서브 클래스 Student의 인스턴스 이면서 동시에 슈퍼 클래스 Person의 인스턴스

👾  어떤 객체가 어떤 클래스의 인스턴스인지 확인하기 위해서 isinstance() 함수를 사용
        ➡️  객체가 인스턴스일 경우에는 True 아니면 False 반환

# isinstance(객체, 클래스)
print(isinstance(potter, Student))  # True
print(isinstance(potter, Person))  # True

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

+ Recent posts