Profile picture

[Python] MySQL에 CSV 데이터 밀어넣기

JaehyoJJAng2022년 09월 05일

▶︎ DB 임포트

  • 다음과 같은 데이터를 가지고 있는 CSV 파일을 파이썬을 사용하여 copang_main 데이터베이스에 저장
id,email,age,gender,height,weight,birthday,sign_up_day,address
1,codeit@naver.com,28,m,178.2,70.0,1992-01-03,2019-03-26,서울특별시 중구 삼일대로 343 103호
2,korin02@google.com,29,m,165.7,67.3,1992-08-13,2019-02-27,서울특별시 중구 세종대로 110 502호
3,cowboy@codeit.kr,31,m,Null,70.2,1990-01-03,2019-01-05,경기도 고양시 일산서구 고양대로 633 204동 203호
4,get_flower@naver.com,-10,f,183.5,72.0,1975-03-12,2018-11-29,Null
5,taehos@hanmail.net,27,m,181.3,70.0,1992-09-02,2017-03-14,제주 제주시 문연로 6 102동 1105호
6,iamstylish@naver.com,300,f,172.2,Null,1989-01-03,2012-11-15,안드로메다 128행성
7,captainGoGo03@koreauniv.com,28,m,195.2,66.0,1992-03-13,2014-03-18,전라남도 순천시 왕지3길 60 112동 107호
8,sungsos@naver.com,36,f,167.7,66.2,1992-01-03,2017-03-20,경기도 부천시 평천로 679 101동 101호
9,young05@naver.com,30,m,180.2,70.4,1991-02-13,2013-08-12,경기 오산시 세마문학로 50 111동 109호
10,codeman_to@yonseit.com,111,f,Null,70.5,1970-08-01,2017-02-20,경기 고양시 덕양구 충장로 118 112동 1103호
11,programmer007@sumsung.com,27,m,170.4,65.3,1993-03-26,2014-01-22,경기 성남시 수정구 시민로 209 101동 1201호
12,lovely_day@kaisty.com,-10,f,162.7,69.4,1995-10-11,2017-07-01,경기 화성시 봉담읍 동화새터길 55-39 203동 205호
13,teddy@kakaot.com,41,f,177.3,77.2,1980-11-12,2016-08-03,인천 부평구 아트센터로 118 302동 602호
14,pooh_man@naver.com,28,m,182.0,Null,1993-12-21,2018-09-02,인천 미추홀구 송림로 194 602동 303호
15,bicycle_go123@yahoot.com,24,m,180.0,60.3,1997-03-03,2019-12-01,서울 송파구 올림픽로 435 103동 501호
16,all_round321@naver.com,26,m,182.4,Null,1995-01-03,2019-11-23,Null
17,nice_man@google.com,200,m,180.8,Null,2003-01-03,2015-10-25,강원도 원주시 가곡로 50 101동 810호
18,jw101@hanmail.net,0,m,160.3,70.0,1992-08-03,2017-09-23,강원도 춘천시 지석로 29 402동 321호
19,cat_movie@lotte.com,-5,f,180.2,Null,1989-01-03,2018-11-25,서울 양천구 오목로 354 110동 402호
20,gogo_shopping@naver.com,32,m,180.2,80.3,1989-11-02,2015-01-23,서울 송파구 올림픽로35길 10 파크리오 301동 703호
21,hello_hat@unista.com,26,f,165.3,48.2,1995-11-13,2018-12-23,Null
22,new_coder@naver.com,-2,f,180.7,70.0,1976-08-03,2018-12-12,부산 연제구 양연로27번길 26 301동 701호
23,zerotohundred@naver.com,20,m,162.0,56.0,2001-02-17,2015-07-20,Null
24,xMan_series@naver.com,29,m,173.0,65.0,1992-01-03,2011-12-20,어린왕자에 나오는 B612

▶︎ CSV 파일 데이터 추출

readcsv.py

from pathlib import Path
from typing import List
import csv
import os

class ReadCSV:
    BASE_DIR : str = Path(__file__).resolve().parent

    @classmethod
    def get_csv_data(cls)-> List[Dict[str,str]]:
        """ csv 패키지의 csv.reader , csv.DictReader 메소드 사용하여 CSV 파일 내의 데이터를 딕셔너리 , 리스트 형태로 추출 후 리턴 """

        save_data = list()
        with open(os.path.join(cls.BASE_DIR,'member-data.csv') , 'r',encoding="UTF-8",errors="",newline="") as file:
            # 리스트 형식
            csv_file_list List[str] = csv.reader(file,delimiter=",",doublequote=True,lineterminator="\r\n",quotechar='"',skipinitialspace=True)
            # 딕셔너리 형식
            csv_file_dict : Dict[str,str] = csv.DictReader(file,delimiter=",",doublequote=True,lineterminator="\r\n",quotechar='"',skipinitialspace=True)

            for row in csv_file_dict:
                save_data.append(row)

        return save_data

▶︎ DB 환경변수 파일 작성

  • DB 환경변수 파일 작성

db_info.json

{
  "host" : "mysql",
  "port" : "3306",
  "user" : "pub",
  "password" : "pub",
  "db" : "copang_main",
  "charset" : "utf8"
}
  • JSON 데이터 추출 클래스 정의

src/dbinfo.py

class GetDBInfo:
    """ 현재 파일의 부모 디렉토리 경로 추출 """
    BASE_DIR = Path(__file__).resolve().parent

    @classmethod
    def get_db_info(
            cls,
            key: str,
            default_value : Optional[str] = None
    ):
        with open(os.path.join(cls.BASE_DIR,'db_info.json') , 'r' , encoding='UTF-8') as file:
            db_info = json.loads(file.read())

        try :
            return db_info[key]
        except:
            if default_value:
                return default_value
            raise EnvironmentError(f'Set the {key}')

▶︎ 추출된 CSV 데이터 DB에 밀어넣기

main.py

from config import DB_INFO , CSV
from typing import Dict,List,Optional
import pymysql
import datetime

class ConnectDB:
    def __init__(self)-> None:
        HOST : str = DB_INFO.get_db_info(key='host')
        PORT : str = DB_INFO.get_db_info(key='port')
        USER : str = DB_INFO.get_db_info(key='user')
        PASSWORD : str = DB_INFO.get_db_info(key='password')
        DB : str = DB_INFO.get_db_info(key='db')
        CHARSET : str = DB_INFO.get_db_info(key='charset')

    @classmethod
    def connect(cls)-> Optional(pymysql.Connect):
        d = datetime.datetime.now()
        try :
            DB : pymysql.Connect = pymysql.connect(host=cls.HOST,port=cls.PORT,user=cls.USER,password=cls.PASSWORD,db=cls.DB,charset=cls.CHARSET)

            sql_query : str = """CREATE TABLE IF NOT EXISTS member(
            id INT NOT NULL PRIMARY KEY,
            email TEXT,
            age INT,
            gender TEXT,
            height DOUBLE,
            weight DOUBLE,
            birthday DATE,
            sign_up_day DATE,
            address TEXT
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"""

            DB.cursor().execute(sql_query)

            print(f'{cls.d.strftime("%Y.%m.%d %H:%M")}\nDB 설정이 완료되었습니다!')

            return DB
        except:
            """ DB 접속 실패 시 프로그램 종료 """
            print("DB 접속에 실패하였습니다.")
            raise Exception

class ImportDB:
    def __init__(self):
        # CSV 데이터 가져오기
        self.csv_datas : List[Dict[str,str]] = CSV.get_csv_data()

        # DB CONNECT Instance
        self.DB : pymysql.Connect = ConnectDB().connect()

    def main(self):
        cursor = self.DB.cursor()

        """ for loop """
        [self.save_to_db(csv_data=csv_data,cursor=cursor,count=count) for count,csv_data in enumerate(self.csv_datas,1)]

        """ DB Connect Quit """
        self.DB.commit()
        self.DB.close()

    def save_to_db(self,csv_data: dict,cursor,count: int):
        print(csv_data , '\n')

        # 데이터 중복 피하기
        sql : str = f"""SELECT COUNT(*) FROM member WHERE id ="{csv_data['id']}";"""
        cursor.execute(sql)
        result = cursor.fetchone()

        if result[0] == 0 :
            sql = f"""INSERT INTO member(id,email,age,gender,height,weight,birthday,sign_up_day,address) VALUES
            ({csv_data['id']},"{csv_data['email']}",{csv_data['age']},"{csv_data['gender']}",{csv_data['height']},{csv_data['weight']},"{csv_data['birthday']}","{csv_data['sign_up_day']}","{csv_data['address']}");"""

            cursor.execute(sql)

        print(f'copang_main 데이터베이스에 데이터가 정상적으로 들어갔습니다! ({count})\n')

if __name__ == '__main__':
    app = ImportDB()

    app.main()

▶︎ 결과 확인하기

SELECT id,email,age,gender,height,weight,birthday,sign_up_day,address FROM member WHERE id > 15;

image


Loading script...