PYTHON

[빅데이터 분석] 2021.12.24 예외처리, 파일 다루기, Pickle 모듈, CSV 파일, 로그 관리, 설정 저장

죠으니 2021. 12. 24. 17:22

오늘은 크리스마스 이브!!!!

우와아아아앙 좋다 히히 오늘 크리스마스 이브니깐 불닭을 먹어야징 ㅇㅁㅇ

아무 논리성 없는 전개 흫 

오늘 배운 내용이 이때까지 배운 것 중에 제일 어려운 것같다ㅠㅠ

읽으면 이해는 가는데,,계속 실행도 해보고 복습도 하고 해야겠다 친해지려면 시간이 좀 걸릴둣,,오늘 하루도 수고했엉!👍

 

 

<예외 처리>

특정 상황에서 실패할 수 있는 코드를 실행할 때, 잠재적 에러 방지를 위해 적절한 예외 처리(exception handler)가 필요

◇try-except 구문

   try:

      예외 발생 가능 코드

   except 예외 타입:

      예외 발생 시 실행되는 코드

for i in range(10):
    try:                                  try는 에러가 나는지 안나는지만 보고 에러가나면 except로 간다
        print(10 / i)
    except ZeroDivisionError:      0으로 숫자를 나눌때
        print("Not divided by 0")

Not divided by 0
10.0
5.0
3.3333333333333335
2.5
2.0
1.6666666666666667
1.4285714285714286
1.25
1.1111111111111112

 try-except-else 구문

   try:

      예외 발생 가능 코드

   except 예외 타입:

      예외 발생 시 실행되는 코드

   else:

      예외가 발생하지 않을 때 실행되는 코드

 

try-except-finally 구문

   try:

      예외 발생 가능 코드

   except 예외 타입:

      예외 발생 시 실행되는 코드

   finally:

      예외 발생 여부와 상관없이 실행되는 코드

try:
    for i in range(1, 10):
        result =10 // i
        print(result)
except ZeroDivisionError:
    print("Not divided by 0")
finally:
    print("종료되었다.")

10
5
3
2
2
1
1
1
1
종료되었다.

 raise 구문 : 에러가 발생했을 때 입력이 잘못된 것을 알려주며 종료

while True:
    value = input("변환할 정수값을 입력해 주세요: ")
    for digit in value:
        if digit not in "0123456789":
            raise ValueError("숫자값을 입력하지 않았습니다.")  raise 예외타입('예외정보')
    print("정수값으로 변환된 숫자: ", int(value))

변환할 정수값을 입력해 주세요: 12
정수값으로 변환된 숫자:  12
변환할 정수값을 입력해 주세요: ㅇ
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_584/149802224.py in <module>
      3     for digit in value:
      4         if digit not in "0123456789":
----> 5             raise ValueError("숫자값을 입력하지 않았습니다.")  #raise 예외타입('예외정보')
      6     print("정수값으로 변환된 숫자: ", int(value))

ValueError: 숫자값을 입력하지 않았습니다.

☞ while문이 true면 계속 반복된다. 
☞ 0~9까지 중에 없으면 ValueError("숫자값을 입력하지 않았습니다.") 이것이 뜬다

 

◇ assert 구문

True or False 결과값이 나오는 함수

특정 조건에 만족하지 않을 경우 예외 발생

def get_binary_nmubmer(decimal_number):
    assert isinstance(decimal_number, int)       입력값이 특정 클래스의 인스턴스인지
    return bin(decimal_number)

 

print(get_binary_nmubmer("10"))
☞ 숫자가 아닌 문자를 넣어주면 에러가 난다

 

<파일 다루기>

▶파일은 기본적으로 바이너리 파일, 텍스트 파일 두 가지로 분류

- 바이너리 파일 : 컴퓨터가 이해할 수 있는 이진 형식으로 저장된 파일

- 텍스트 파일 : 사람도 이해할 수 있는 문자열 형식으로 저장된 파일

 

◇ 파일 읽기

open() 함수 : 파이썬에서 텍스트 파일을 다루기 위해 사용하는 함수

  txt파일은 open을 이용하여 파일을 열 수 있다.

   f = open(“파일명”, “파일 열기 모드”)    r은 읽기모드, w는 쓰기 모드, a는 추가 모드

   f.close()

UTF-8-SIG 인코딩 에러날 때 활용!

   f = open("dream.txt", "r", encoding='UTF-8')  # 파일 객체 f에 파일 정보 저장 
   contents = f.read()                                   # read() 함수로 해당 파일의 텍스트를 읽어서 contents 변수에 저장
   print(contents)                                        # 저장된 변수 출력
   f.close()                                                 # 파일 읽은 후 close() 함수로 파일 종료해야 됨

I have a dream a song to sing
to help me cope with anything
if you see the wonder of a fairy tale
you can take the future even
if you fail I believe in angels
something good in everything

with문 + open 함수로 파일 열기 : close() 사용하지 않아도 들여쓰기가 끝나면 파일 사용 종료됨

  해당 파일 객체는 =로 할당하지 않고, as문을 사용하여 변수명에 할당함.

with open("dream.txt","r", encoding='UTF-8') as my_file:
       contents = my_file.read()
       print(contents)

▶ readlines() 함수로 한 줄씩 읽어서 리스트형으로 반환하기

-한 줄의 기준은 \n으로 나뉘며 한 줄씩 리스트 요소로 반환된다.

with open("dream.txt","r", encoding='UTF-8') as my_file:

    content_list = my_file.readlines()      # 파일 전체를 리스트로 반환
    print(type(content_list))               # 자료형 확인
    print(content_list)                     # 리스트값 출력

<class 'list'>
['I have a dream a song to sing\n', 'to help me cope with anything\n', 'if you see the wonder of a fairy tale\n', 'you can take the future even\n', 'if you fail I believe in angels\n', 'something good in everything\n']

☞ \n은 줄바꿈 표시다

▶readline() 함수로 실행할 때마다 한 줄씩 읽어오기

-내용을 찾다가 중간에 특정 작업을 하거나 멈춰야 할 필요가 있는 대용량 데이터에서 사용

with open("dream.txt","r", encoding='UTF-8') as my_file:

    i = 0
    while 1:
        line = my_file.readline()
        if not line:                                            # 읽어온 줄에 내용이 없다면 파일 읽기 종료
            break                                              #break는 빠져나가라 라는 뜻. 문장이 없으면 종료됨
        print(str(i)+" === "+ line.replace("\n",""))    # 한 줄씩 값 출력. replace("\n","")은 \n을 ""으로 바꿔주는 것
        i = i + 1

0 === I have a dream a song to sing
1 === to help me cope with anything
2 === if you see the wonder of a fairy tale
3 === you can take the future even
4 === if you fail I believe in angels
5 === something good in everything

파일 안 글자의 통계 정보 출력하기

with open("dream.txt", "r", encoding='UTF8') as my_file:
    contents = my_file.read()
    word_list = contents.split(" ")             # 빈칸 기준으로 단어를 분리 리스트
    line_list = contents.split("\n")            # 한 줄씩 분리하여 리스트

print("총 글자의 수:", len(contents))
print("총 단어의 수:", len(word_list))
print("총 줄의 수:", len(line_list))

총 글자의 수: 205
총 단어의 수: 36
총 줄의 수: 12

◇ 파일 쓰기

▶새로운 텍스트 파일에 텍스트 저장

- open(‘저장할 파일명.txt’, ‘w’ 모드, encoding=‘utf8’)

   f = open("count_log.txt", 'w', encoding = "utf8")         #쓰기라서 w가 들어감
   for i in range(1, 11):
       data = "%d번째 줄이다.\n" % i
       print(data)
       f.write(data)
   f.close()

1번째 줄이다.

2번째 줄이다.

3번째 줄이다.

4번째 줄이다.

5번째 줄이다.

6번째 줄이다.

7번째 줄이다.

8번째 줄이다.

9번째 줄이다.

10번째 줄이다.

◇ 파일 추가 모드

▶‘w’ 모드는 항상 새로운 파일을 생성하기 때문에, 또 실행하면 기존 파일을 삭제하고 새로 생성한다.

  기존 파일에 새로운 내용을 추가하려면 ‘a’ 추가 모드를 사용하면 된다.

with open("count_log.txt", 'a', encoding = "utf8") as f:

      for i in range(1, 11):
          data = "%d번째 줄이다.\n" % i
          print(data)
          f.write(data)

 

◇ 디렉터리 만들기(디렉터리는 폴더다)

os 모듈을 사용하면 디렉터리를 쉽게 만들 수 있다.

   import os
   os.mkdir("log")

▶기존 디렉토리가 없는 경우에만 만들도록 할 수도 있다.

☞ 기존 디렉터리가 없는지 확인하고 만들기

import os

if not os.path.isdir("log"):
    os.mkdir("log")

 

◇로그파일 만들기

▶프로그램이 작동하는 동안 여러 가지 중간 기록을 하는 파일

ex. 웹 프로그램의 경우 접소 기록, 접속 시간

import os                                                          # 디렉토리 경로 지정할 때 무지 편한 모듈

# 로그 디렉토리 생성
if not os.path.isdir("log"):
    os.mkdir("log")

# 기록 파일 생성 후 기록 시작 문구 저장
if not os.path.exists("log/count_log.txt"):                     #log안에 count_log.txt가 존재하는지 보는것
    f = open("log/count_log.txt", 'w', encoding = "utf8")
    f.write("기록이 시작된다.\n")
    f.close()

 

# 시간(stamp)과 특정값(vlaue)을 기록한 후 저장
with open("log/count_log.txt", 'a', encoding = "utf8") as f:
    import random, datetime
    for i in range(1, 11):
        stamp = str(datetime.datetime.now())  # 현재 시간
        value = random.random() * 1000000
        log_line = stamp + "\t" + str(value) + "값이 생성되었다." + "\n" #stamp 현재시간이다
        f.write(log_line)

 

<Pickle 모듈>

▶ 파이썬은 pickle 모듈을 지원하여 메모리에 로딩된 객체를 저장해두어서 영속화할 수 있도록 함.

☞ 리스트의 데이터나 클래스의 객체 등을 파일로 저장하여 나중에 다시 사용 가능

☞ 리스트의 데이터를 pickle 파일로 저장하기 : ‘wb’ 모드

☞ 저장된 pickle 파일 불러오기 : ‘rb’ 모드

▶ ‘wb’ 모드

   import pickle

   f = open("list.pickle", "wb")
   test = [1,2,3,4,5]
   pickle.dump(test, f)             #dump는 덮어씌어주는 것
   f.close()

 

▶‘rb’ 모드

   f = open("list.pickle", "rb")
   list_pickle = pickle.load(f)
   print(list_pickle)
   f.close()

[1, 2, 3, 4, 5]

클래스로 생성된 인스턴스를 pickle 파일로 저장하기

클래스로 인스턴트 생성

# 곱셈기 클래스
#  Multiply 는 곱셈이다
class Multiply(object):
    def __init__(self, multiplier):
        self.multiplier = multiplier
    
    # 곱셈 메소드
    def multiply(self, number):
        return number * self.multiplier

 

 인스턴스 생성
multiplier = Multiply(5)

인스턴스pickle 파일로 저장하기
import pickle

f = open("multiply_object.pickle", "wb")
pickle.dump(multiplier, f)
f.close()

▶저장된 pickle 파일 읽기
f = open("multiply_object.pickle", "rb")
multiply_pickle = pickle.load(f)
multiply_pickle.multiply(10)

 

<CSV 파일>

 CSV : 콤마를 기준으로 나누어진 값

- 엑셀 형태의 데이터를 텍스트 형태로 다루는 형식

- 엑셀은 MS 오피스에서 메인으로 작동하는 바이너리 파일(binary file) 형식이지만,

  csv는 어디서나 큰 문제없이 사용할 수 있는 텍스트 데이터이다.

- 엑셀 파일에서 만들 수 있다.

  파일 -> 다른 이름으로 저장 -> “파일 형식 : CSV” 로 저장

 

교재 코드로 csv 파일 읽기 

line_counter = 0            # 파일의 총 줄 수를 세는 변수
data_header = [ ]           # 데이터의 필드값을 저장하는 리스트
customer_list = [ ]         # customer의 개별 리스트를 저장하는 리스트

with open("customers.csv") as customer_data: # customers.csv 파일을 customer_data 객체에 저장
    while 1:
        data = customer_data.readline()     # customers.csv에 데이터 변수에 한 줄씩 저장
        if not data:break                   # 데이터가 없을 때, 반복문 종료
        if line_counter == 0:               # 첫 번째 데이터는 데이터의 필드
            data_header = data.split(",")   # 데이터의 필드는 data_header 리스트에 저장, 데이터 저장 시 ","로 분리
        else:
            customer_list.append(data.split(",")) # 일반 데이터는 customer_list 객체에 저장, 데이터 저장 시 “,”로 분리
        line_counter +=1

print("Header:", data_header)               # 데이터 필드값 출력
for i in range(0, 10):                      # 데이터 출력(샘플 10개만)
    print("Data",i,":",customer_list[i])
print(len(customer_list))                   # 전체 데이터 크기 출력

Header: ['customerNumber', 'customerName', 'contactLastName', 'contactFirstName', 'phone', 'addressLine1', 'addressLine2', 'city', 'state', 'postalCode', 'country', 'salesRepEmployeeNumber', 'creditLimit\n']
Data 0 : ['103', 'Atelier graphique', 'Schmitt', 'Carine ', '40.32.2555', '"54', ' rue Royale"', 'NULL', 'Nantes', 'NULL', '44000', 'France', '1370', '21000\n']
Data 1 : ['112', 'Signal Gift Stores', 'King', 'Jean', '7025551838', '8489 Strong St.', 'NULL', 'Las Vegas', 'NV', '83030', 'USA', '1166', '71800\n']
Data 2 : ['114', '"Australian Collectors', ' Co."', 'Ferguson', 'Peter', '03 9520 4555', '636 St Kilda Road', 'Level 3', 'Melbourne', 'Victoria', '3004', 'Australia', '1611', '117300\n']
Data 3 : ['119', 'La Rochelle Gifts', 'Labrune', 'Janine ', '40.67.8555', '"67', ' rue des Cinquante Otages"', 'NULL', 'Nantes', 'NULL', '44000', 'France', '1370', '118200\n']
Data 4 : ['121', 'Baane Mini Imports', 'Bergulfsen', 'Jonas ', '07-98 9555', 'Erling Skakkes gate 78', 'NULL', 'Stavern', 'NULL', '4110', 'Norway', '1504', '81700\n']
Data 5 : ['124', 'Mini Gifts Distributors Ltd.', 'Nelson', 'Susan', '4155551450', '5677 Strong St.', 'NULL', 'San Rafael', 'CA', '97562', 'USA', '1165', '210500\n']
Data 6 : ['125', 'Havel & Zbyszek Co', 'Piestrzeniewicz', 'Zbyszek ', '(26) 642-7555', 'ul. Filtrowa 68', 'NULL', 'Warszawa', 'NULL', '01-012', 'Poland', 'NULL', '0\n']
Data 7 : ['128', '"Blauer See Auto', ' Co."', 'Keitel', 'Roland', '+49 69 66 90 2555', 'Lyonerstr. 34', 'NULL', 'Frankfurt', 'NULL', '60528', 'Germany', '1504', '59700\n']
Data 8 : ['129', 'Mini Wheels Co.', 'Murphy', 'Julie', '6505555787', '5557 North Pendale Street', 'NULL', 'San Francisco', 'CA', '94217', 'USA', '1165', '64600\n']
Data 9 : ['131', 'Land of Toys Inc.', 'Lee', 'Kwai', '2125557818', '897 Long Airport Avenue', 'NULL', 'NYC', 'NY', '10022', 'USA', '1323', '114900\n']
122

cf) pandas로 csv 파일 읽기

import pandas as pd
df = pd.read_csv("customers.csv")
print(df.shape)
df

 

<로그 관리>

로깅 : 프로그램이 실행하는 동안 일어나는 정보를 파일이나 기록에 남기는 일

import logging

 

logger = logging.getLogger("main")           # logger 객체에 로그를 기록할 예정
stream_handler = logging.StreamHandler()  # StreamHandler : 출력 공간 지정
logger.addHandler(stream_handler)            # logger 의 출력 등록

logger.setLevel(logging.CRITICAL)              # 로깅 레벨 지정. logging뒤에 debug넣으면 "틀렸자나"가 나옴
logging.debug("틀렸잖아!")
logging.info("확인해!")
logging.warning("조심해!")
logging.error("에러 났어!!!")
logging.critical ("망했다….")

 

<설정 저장>

ex. 쥬피터 노트북의 설정 : 배경색, 글씨 폰트, 파일 저장 위치 등

설정 저장이 필요한 이유 : 매번 프로그램을 사용할 때마다 환경을 동일하게 세팅하기 위해

파이썬에서의 설정 저장 모듈

- configparser : 미리 설정을 저장해두고, 실행 시점에 설정이 저장된 파일을 읽어와 설정을 적용

- argparse : 실행 시점에 설정 변수를 직접 지정. 프롬프트에서 실행해서 설정 입력

 

configparser 모듈

import configparser
config = configparser.ConfigParser()
config.sections()

config.read("example.cfg")

['example.cfg']

▶config.sections()

['SectionOne', 'SectionTwo', 'SectionThree']

▶for key in config['SectionOne']:
    print(key)

status
name
value
age
single

▶config['SectionOne']["status"]

'Single'

 

 

<함수와 메소드의 차이>

-함수는 print() type() str() int() bool() 처럼 독립적으로 활용

-메소드는 .split() .append() 처럼 앞에 특정 객체(object)가 있어야 함.

  위의 경우 . 앞에 문자열이 붙어 있어야 함.