본문 바로가기
LG 헬로비전 DX DATA SCHOOL/Python

Python 예외처리 / File handling

by 황밤 2023. 7. 14.
728x90
반응형

2023-07-14

 

2023.07.11 - [LG 헬로비전 DX DATA SCHOOL/Python] - 파이썬 Data Type 및 처리

 

파이썬 Data Type 및 처리

2023-07-11/ ~ /0713 2023.07.11 - [LG 헬로비전 DX DATA SCHOOL/Python] - 객체 지향 프로그래밍 (OOP) 객체 지향 프로그래밍 (OOP) 2023-07-11 오늘은 저번 시간에 이어서 파이썬에서의 객체지향 프로그래밍에 대해서

dxdata.tistory.com

이전 글입니다

 

예외 처리의 간단한 설명도 같이 있습니다!

 

저번에 이어서 예외처리에 대해서 알아보겠습니다!

 

1. 예외 처리

 

1.1) 예외

  • 문법적인 오류는 없어서 실행은 되지만 실행 도중 발생한 예기치 않은 상황으로 인해 프로그램이 중단되는 현상

 

1.2) 예외처리

  • 예외가 발생했을 때 비정상 종료를 하지 않고 정상적인 수행을 하도록 처리하는 것

 

1.3) 기본형식

try : 

        예외가 발생할 가능성이 있는 구문

except :

        예외가 발생했을 때 수행할 내용

 

1.4) 예외를 종류 별로 처리하기

  • except 다음에 예외 클래스 이름을 기재한 후 처리하는 코드를 작성하면 예외 클래스 이름에 해당하는 예외가 발생했을 때 구문을 수행합니다.
  • except 는 여러 개 작성이 가능한데, if~ elif 처럼 동작 (예외 하나씩 수행)
ar = [10, 20, 30]

su = int(input("나눌 수를 입력하세요:"))

i = 0
#while i <= len(ar) : # len이라는 함수로 고정값을 찾아오기 보단 미리 수를 받아오는게 좋다.
j = len(ar)

try :
    while i < j :
        print(ar[i] / su)
        i = i + 1
#나눗셈의 return 값은 기본적으로 float!!!!
except ValueError:
    print("잘못된 값을 입력했어요")

except ZeroDivisionError :
    print("0으로 나눌 수는 없습니다")

print(type(ar[1]/su))

 

1.5) 예외 내용을 받아서 처리하기

 

except 예외 클래스 이름 as 변수명 :

  • 위의 경우에는 예외 내용을 변수에 대입하게 됩니다.
  • 변수를 출력하면 어떤 예외가 발생했는지 알 수 있습니다.
ar = [10, 20, 30]

su = int(input("나눌 수를 입력하세요:"))

i = 0
#while i <= len(ar) : # len이라는 함수로 고정값을 찾아오기 보단 미리 수를 받아오는게 좋다.
j = len(ar)

try :
    while i < j :
        print(ar[i] / su)
        i = i + 1
#나눗셈의 return 값은 기본적으로 float!!!!
except ValueError as e : #as e를 추가하고 밑에 print!
    print("잘못된 값을 입력했어요")
    print(e)
except ZeroDivisionError as e:
    print("0으로 나눌 수는 없습니다")
    print(e)

 

 

 

1.6) 예외 클래스 계층

https://docs.python.org/3/library/exceptions.html

 

Built-in Exceptions

In Python, all exceptions must be instances of a class that derives from BaseException. In a try statement with an except clause that mentions a particular class, that clause also handles any excep...

docs.python.org

 

들어가서! 확인이 가능합니다.

 

 

 

 

1.7) except 뒤에 추가할 수 있는 절

 

  • else 절 : 예외가 발생하지 않고 정상적으로 처리가 수행된 경우 수행할 내용, 정상적인 처리 다음에 수행할 내용을 작성
  • finally 절 : 예외 발생 여부에 상관없이 수행할 내용, 이 절에는 외부 자원에 대한 연결을 해제하는 문장을 주로 작성
  • else 와 finally를 같이 사용하고자 하는 경우에는 else를 먼저 작성해야 합니다. finally는 예외 처리 구문이 종료됨을 의미합니다.

 

1.8) 강제로 예외를 발생시키기

  • raise Exception(메시지) : 현재 함수 내에서 예외를 처리합니다.
  • raise : 호출하는 함수로 예외를 던지기(예외를 발생시켜버림. 다른 언어들은 throw/throws, 단 Oracle은 똑같이 raise로 예외를 발생 - 데이터 베이스에서 예외는 처리를 안해주겠다라는 의미)

 

9)assertion(단언)

  • 강제로 프로그램을 중단하는 것

assert 프로그램이 중단되지 않는 조건 [,에러메세지(생략 가능)]

ar = [10, 20, 30]

su = int(input("나눌 수를 입력하세요:"))

i = 0
#while i <= len(ar) : # len이라는 함수로 고정값을 찾아오기 보단 미리 수를 받아오는게 좋다.
j = len(ar)

try :
    while i < j :
        if su == 1 :
            raise ValueError("강제로 예외 발생") #raise 이용 예외처릐
        assert su != 2, 'su는 2이면 안됩니다.'
        #수에 2가 입력되면 프로그램은 중단됩니다 -> assertion
        print(ar[i] / su)
        i = i + 1
#나눗셈의 return 값은 기본적으로 float!!!!
except ValueError as e : #as e를 추가하고 밑에 print!
    print("잘못된 값을 입력했어요")
    print(e)
except ZeroDivisionError as e:
    print("0으로 나눌 수는 없습니다")
    print(e)
else :
    print("예외가 발생하지 않은 경우 수행할 내용")

finally :
    print("무조건 수행하는 문장")

 

2. File Handling

2.1) 파일 처리 과정

  • open 이라는 함수를 이용해서 운영체제에게 파일을 사용할 수 있도록 요청
  • 파일이 존재하면 파일에 대한 참조를 리턴을 하고 파일이 존재하지 않으면 생성을 하던가 아니면 예외를 발생시킴.
  • 파일에 대한 읽고 쓰기 작업을 함수를 이용해서 수행하면 운영체제가 작업을 수행하고 그 결과를 리턴
  • close 함수를 이용해서 파일을 닫습니다.

 

2.2)파일 쓰기 작업

  • open 함수에 2개나 3개의 매개변수를 대입해서 파일을 열기
  • 첫번째 매개변수는 파일의 경로이고 두번째는 'w'이고 세번째 인코딩 방식(생략하면 시스템 인코딩 - utf-8
  • 기록을 할 때는 파일 참조 변수를 이용해서 write를 호출
  • \n이 포함된 컬렉션의 경우는 writelines 나 join을 이용해서 줄 단위 기록이 가능

 

2.3) 파일 읽기 작업

  • open 함수에 1개나 2개의 매개변수를 대입해서 파일을 열기
  • 첫번째 매개변수는 파일 경로
  • 두번째 매개변수로 'r'을 대입할 수 있는데 생략하면 'r' 
  • read()를 사용하면 전체를 읽어옴
  • readline()을 이용하면 줄 단위로 읽고 readlines 는 줄 단위로 읽어서 list로 리턴
  • read(정수)는 정수 바이트 만큼 읽어옴

 

2.4)현재 작업 디렉토리 확인 및 변경

  • os.getcwd() : 현재 작업 디렉토리를 리턴
  • os.chdir('디렉토리') : 현재 작업 디렉토리 변경
try :
    file = open('./data/test.txt', 'w', encoding = 'utf-8')
    file.write("안녕") #문자열 기록
    lines = ["김좌진", "김홍도", "김구"]
    file.writelines(lines)
except Exception as e :
    print("파일 처리 중 예외 발생", e)
  • 파일을 열어서 내용을 확인 - 한글이 깨지면 open 함수에 encoding="인코딩 방식"을 추가해서 인코딩 설정을 추가해야 한다.

 

2.5) with 절

  • 파일은 외부 자원이라서 열어서 사용하고 작업이 끝나면 close를 호출해서 해제를 해야 한다.
  • close 구문은 finally에 작성해서 예외 발생 여부에 상관없이 해제를 해야 한다.

-> with open() as 파일변수 :

  • 위와 같이 작성하게 되면 open의 리턴 값을 파일 변수에 저장하고 with 절이 끝나며 예외 발생 여부에 상관없이 자동으로 close()를 호출합니다.
with open('./data/test.txt', encoding = 'utf-8') as file :
    #줄 단위 읽기
    for line in file :
        print(line)
        print()

 

 

3. csv 파일

3.1) 텍스트 파일 : 문자열을 기록한 파일

  • 텍스트 파일을 데이터를 저장하는 용도로 사용이 가능 
  • fwt : 일정한 간격을 갖는 텍스트
  • tsv : 탭으로 구분한 텍스트
  • csv : 쉼표로 구분한 텍스트
  • 최근에는 구분자로 구분된 것은 모두 csv 라고 함
  • 불변의 데이터인 경우는 csv로 제공하는 것이 일반적

 

 

 

3.2) csv 읽고 쓰기

  • 텍스트로 읽어서 split 같은 메서드를 이용 : 문자열 내에 따옴표가 있는 경우 해석이 잘 안되는 경우가 발생
  • 파이썬이 제공하는 csv 모듈을 이용하는 방법
  • pandas 와 같은 외부 라이브러리를 이용하는 방법
#텍스트 파일을 읽어서 list로 변환, 마지막 데이터는 \n이 추가됩니다.
#마지막 데이터는 \n을 제거해주어야 합니다.
import re
data = []
with open('./data/test.csv', encoding='utf-8') as file :
    for line in file :
        ar = line.split(",")
        data.append(ar)

#re.sub(r'\n','' ,data)

print(data)
  • 파이썬이 제공하는 csv 모듈을 이용하는 방법

파일 객체를 csv.reader 객체에 대입하면 줄단위로 읽을 수 있는 reader 객체를 리턴하는데 이 객체를 for로 순회 하면 각 줄을 list로 변환해서 접근할 수 있도록 해준다.

읽거나 기록을 할 때 

 

#줄단위로 읽어서 list를 만들어주는 reader객체
import csv
data = []
with open('./data/test.csv', encoding='utf-8') as file :
    rdr = csv.reader(file)
    for line in rdr :
        data.append(line)

print(data)

 

csv.writer 에 파일 객체를 대입하면 csv에 기록이 가능한 객체를 생성할 수 있는데 이 객체를 가지고 writerow(list)를 호출하면 csv 파일에 기록도 가능합니다.

 

import csv
data = []
#w모드는 지우고 기록, r은 읽기 전용, a 는 기존 내용 뒤에 추가
with open('./data/test.csv', 'a',encoding='utf-8') as file :
    wr = csv.writer(file)
    wr.writerow(['이강인', '김민재', '최진철'])
    wr.writerow(['이천수', '배준호', '황성주'])

print(data)

 

 

 

3. 바이너리 파일과 Serializable

3.1) 바이너리 파일

  • 바이트 단위로 파일에 기록하고 읽기
  • 바이너리 파일로 만들 때는 문자열을 직접 기록할 수 없고 encode()를 호출해서 바이트 단위로 기록.
  • 바이너리 파일에서 읽은 데이터를 문자열로 변환할 때 decode()를 호출해야 합니다.
  • 모드를 설정할 때 b 자를 추가
  • 실제로는 텍스트 보다는 이미지 등을 저장할 때 사용
#바이트 단위로 기록하기!
with open('./data/test.bin', 'wb') as file :
    file.write("안녕하세요".encode())
with open('./data/test.bin', 'rb') as file :
    content = file.read()
    print(content.decode())

 

 

3.2) Serializable

  • 인스턴스를 파일에 기록하고 읽거나 네트워크를 통해서 전송하기 위한 작업
  • 입출력은 기본적으로 byte 단위 나 character 단위로만 가능한데 사용자 정의 클래스의 인스턴스 단위로 가능하도록 하는 작업입니다.
  • 이 작업을 하는 경우는 응용 프로그램을 만들고 여기서 생성된 데이터를 다른 곳에서 함부로 읽지 못하도록 하기 위해서 입니다. 
  • 기록

pickle(출력할 객체, 파일 객체)

읽기

pickle.load(파일 객체) : 객체 1개를 읽기

pickle.

 

3.3) DeSerializable

class DTO :
    def __init__(self, num=0, name="이름 없음"):
        self.__num = num #private 으로 만들려면 __num 삽입
        self.__name = name

    @property
    def num(self):
        return self.__num

    @property
    def name(self):
        return self.__name #getter
    @num.setter
    def num(self, num):
        self.__num = num

    @name.setter
    def name(self, name):
        self.__name= name

    #인스턴스를 print 함수에 대입했을 때 호출되는 메서드 : overriding
    #출력을 편리하기 위해서 재정의 - 디버깅 목적
    def __str__(self):
        return str(self.__num) + ":" + self.__name

#파일에 기록할 데이터 생성
dto1 = DTO(1, "원빈")
dto2 = DTO(2, "아이유")

data = [dto1, dto2]

import pickle
 try :
     with open("./data/data.dat", "wb") as f :
         #f에 data를 Serializable
         pickle.dump(data, f)

 except Exception as e:
     print(e)

try :
    with open("./data/data.dat", "rb") as f :
        #f에 data를 DeSerializable
        result = pickle.load(f)
        for dto in result :
            print(dto)
except Exception as e:
    print(e)

 

 

 

4. 파일 압축

4.1) zip 파일 압축

  • zipfile 모듈의 ZipFile 함수를 이용해서 인스턴스를 생성하고 파일 경로를 list로 만든 후 write 함수에 대입하면 압축이 됩니다.
  • zipfile 해제는 extractall 함수를 호출하면 됩니다.
import zipfile
#압축할 파일 목록 생성
filelist = ["./data/data.dat", "./data/test.bin"]
#파일 목록을 순회하면서 압축
with zipfile.ZipFile('./data/test.zip', 'w') as myzip :
    for temp in filelist:
        myzip.write(temp)
        
        
 #압축해제
zipfile.ZipFile("./data/test.zip").extractall()

 

4.2) tar(리눅스 압축 파일 표준) 파일 압축

  • tarfile 모듈 사용

 

5. 로그 파일 읽기

5.1) Apache Tomcat 의 로그 파일

180.76.15.5 - - [15/Nov/2015:03:45:45 +0000] "GET / HTTP/1.1" 200 6812 (200이면 성공, 6812는 traffic)

  • 공백 9개로 분리되는 데이터 -> 실제 항목은 10개
  • 첫번째 항목은 접속한 IP
  • 9번째 항목은 응답 코드로 200이면 성공
  • 열번째 항목은 트래픽(전송량)
#로그 파일 분석 해보장!

import re
path = "./data/log.txt"
data = []
# cnt = 0
#응답 코드가 200인 데이터 세기

#ip 별 접속 회수 세기
d_list = []
f_list = []
ipCount = {}
with open(path) as f : #한글이 없으면 encoding 안해도 됨.

    for line in f :
        #print(line)

        #읽어낸 한 줄을 공백을 기준으로 분할해서 list로 생성
        a = line.split(" ")
        # if a[8] == '200' :
        #     cnt = cnt+1
    #     f_list.append(a[0])
    #     if a[0] not in d_list :
    #         d_list.append(a[0])
    #리스트를 이용해 ip 언급된 횟수 추출
    #     data.append(a)
    #
    # for i in d_list :
    #     cnt = f_list.count(i)
    #     print(cnt)

        ipCount[a[0]] = ipCount.get((a[0]), 0)+1
for ip in ipCount :
  print(ip,":", ipCount[ip])
#print(data)


#print("정상 승인의 개수는:",cnt)


from collections import Counter

#ip별 트래픽 합계 구하기
ipTraffic = {}
with open(path) as f : #한글이 없으면 encoding 안해도 됨.

    for line in f :
        #print(line)
        #읽어낸 한 줄을 공백을 기준으로 분할해서 list로 생성
        a = line.split(" ")


        try :
            ipTraffic[a[0]] = ipTraffic.get((a[0]), 0) + int(a[9]) #'-'를 제거해줘야함.

        except Exception as e:
            print(e)
for ip in ipTraffic :
     print(ip,":", ipTraffic[ip])

#상위 10개
counter = Counter(ipTraffic)
print(counter.most_common(10))

위와 같은 코드로 로그 분석을 수행 해볼 수 있다.

반응형
LIST

'LG 헬로비전 DX DATA SCHOOL > Python' 카테고리의 다른 글

Django REST API  (0) 2023.07.27
Django  (0) 2023.07.26
파이썬 Data Type 및 처리  (0) 2023.07.11
객체 지향 프로그래밍 (OOP)  (0) 2023.07.11
Python - 제어문과 함수 2  (0) 2023.07.10