Python

파이썬 기초문법 8 <예외처리, finally, 모듈, 패키지>

sogummi 2023. 3. 23. 11:06

<예외처리(Exception Handling)>
- 프로그램에서 예외가 발생했을 때, 예외를 핸들링하는 기능
- try블록 내 문장에서 예외가 발생하면, except문으로 이동하여 예외처리를 함
- try문은 또한 finally문을 가질 수 있는데 이것은 try블록이 완료된 후 항상 실행
- 예외처리를 사용하면 프로그램이 예외를 처리하고 계속 실행할 수 있기 때문에 프로그램이 안정적이게 도미

예외처리 1번째 예시
try:
    # 예외가 발생할 가능성이 있는 코드
    a = int(input("첫 번째 숫자를 입력하세요 : "))
    b = int(input("두 번째 숫자를 입력하세요 : "))
    result = a / b
except ZeroDivisionError:
    # ZeroDivisionError 예외가 발생했을 경우 실행될 코드
    print("0으로 나눌 수 없습니다.")
except ValueError:
    # ValueError 예외가 발생했을 경우 실행될 코드
    print("잘못된 입력입니다. 숫자를 입력해주세요.")
else:
    # 예외가 발생하지 않았을 경우 실행될 코드
    print("결과 : {0} / {1} = {2}".format(a, b, result))
finally:
    # 예외 발생 여부와 상관없이 항상 실행될 코드
    print("프로그램 종료")

 

예외처리 - def사용 2번째 예시
def divide(a, b):
    if a == 0 or b == 0:
        raise ZeroDivisionError("0으로 나눌 수 없습니다.")
    return a // b


try:
    print("나누기 할 숫자를 입력해주세요: ")
    a = int(input("1번 값: "))
    b = int(input("2번 값: "))
    result = divide(a, b)

except ZeroDivisionError as e:
    print(e) #ZeroDivisionError 객체가 가진 message 출력
else:
    print(result)
finally:
    print("프로그램 종료")

<사용자 정의 예외>
- Exception을 상속받아 새로운 클래스를 만들어서 정의함
- raise : raise 키워드는 개발자가 직접 예외를 발생시킬 때 사용

사용자 정의 예외 1번째 예시
 
class MyError(Exception): #Exception상속
    def __init__(self, message, error_code): #message, error_code를 인자로 받음
        super().__init__(message) #부모클래스의 생성자 호출하면서 예외 객체의 메세지 문자열 설정 
        self.error_code = error_code #추가적인 에러정보 전달

def foo():
    try:
        x = int(input('한 자리 숫자를 입력하세요: '))
        if x >= 10:
            raise MyError("Something went wrong", 123)
        print(x)
    except Exception as e:
        print('예외가 발생했습니다', e)
        if isinstance(e, MyError):
            print('에러 코드:', e.error_code
foo()

- MyError클래스는 Exception클래스의 서브클래스임
- Exception클래스는 message속성과 args속성을 갖고있고, 파이썬 3.x버전에서는 args속성을 권장함
- args 속성을 사용하면 예외 객체 생성자에서 전달된 인자들을 튜플형태로 갖음 

사용자 정의 예외 - args속성을 사용한 2번째 예시
 
class MyError(Exception):  # Exception상속
    def __init__(self, args1, args2, error_code):  # message, error_code를 인자로 받음
        super().__init__(args1, args2)
        self.error_code = error_code  # 추가적인 에러정보 전달


def foo():
    try:
        x = int(input('한 자리 숫자를 입력하세요: '))
        if x >= 10:
            raise MyError("Something went wrong", "예외메세지", 123
        print(x)
    except Exception as e:
        print('예외가 발생했습니다', e.args)
        if isinstance(e, MyError):
            print('에러 코드:', e.error_code)

foo()예외 발생 시 실행순서 :

위 코드 실행순서:

try블록 내 input()함수 -> 입력받기 -> int()함수에의해 정수로 변환 -> if조건문에서 x값 검사 -> x값이 10이상이면, MyError예외 발생하며 (args1, args2, error_code) 인자 값 전달 -> 예외 발생 시 프로그램이 try블록 종료 후 except블록으로 이동 -> except블록에서 발생한 예외 객체 e 처리 -> 예외메세지 출력 ->if isinstance(e,MyError)가 True이므로, e.error_code 속성값 출력 -> 프로그램 종료 

<모듈화>
- 파이썬 코드를 재사용하기 위해 함수, 클래스, 변수 등의 코드 블록들을 하나의 파일에 담아 모듈이라는 형태로 만듬
 => 코드 재사용성 유지보수성 향상, 협업 시 코드 공유하고 활용할 때 유용함 
- 파일 내에 코드블록 정의, .py 사용
- 모듈을 다른 파이썬 파일에서 사용하고자 할 때는 import문을 사용해서 모듈가져옴
- import하면 모듈안에 정의된 함수, 클래스, 변수 등을 사용가능
- 모듈 안의 요소에 접근하려면 점 연산자(.) 이용 
- as 키워드를 이용해서 모듈 이름을 별칭으로 변경가능 (ex: import mymodule as mv) 
- 만든 모듈 파일을 사용할 파일은 서로 같은 경로상에 위치해야 함 주의!!

영화 극장 가격 모듈파일
prac2 파일에서 만든 모듈파일 import하고 출력

from theater_module import * # theater_module 내에서 모든 것을 가져다가 사용
price(3) # from에 있는 단어 안적어줘도 됨!
price_morning(4)
price_soldier(5)
 
from theater_module import price_soldier as price # price_soldier 를 새로운 별명인 price 로 사용
price(5) # 모듈파일에 작성했던 price함수가 아닌 price_soldier() 를 호출

<패키지(Package)> 
- 여러 개의 모듈(Module)을 묶어서 관리하기 위한 디렉토리(Directory)
- 패키지 안에는 서브 패키지와 모듈을 포함할 수 있음
- 패키지는 '__init__.py'파일을 포함해야 한다!
  (__init__.py파일은 해당 디렉토리를 패키지로 인식할 수 있게 하는 파이썬 파일. 이 파일을 이용해서 패키지의 초기화 코드를 실행하거나 패키지에서 사용가능한 모듈을 정의할 수 있음) 

mypackage
 ├  __init__.py
 ├  Japan.py
 └  Jeju.py
 
---------Japan.py파일 코드 ----------
class JapanTripPackage:
    def detail(self):
        print("패키지 일본 여행 선물권")
 
-----------prac2.py파일에서 import-------------
import
mypackage.Japan

travel = mypackage.Japan.JapanTripPackage()
travel.detail()
 
import 여러 예시 
import mypackage.Japan.JapanTripPackage 클래스 명 직접 import 불가 
travel = mypackage.Japan.JapanTripPackage()
travel.detail()
 
from mypackage.Japan import JapanTripPackage
travel = JapanTripPackage()
travel.detail()

<패키지에서의 __all__> 
- 외부에서 모듈을 import할 때 불러올 수 있는 public을 정의하는 변수
- 모듈 안에서 __all__리스트에 포함된 이름만 import될 수 있다
- mypackage패키지의 '__init__.py'파일에서 __all__ = ['module1', 'module2']와 같이 정의하면 
from 모듈파일명 improt * 형식에서도 출력이 가능하다 

travel #패키지디렉토리 
 ├  __init__.py
 ├  thailand.py  #모듈
 └  vietnam.py  #모듈 
 
-------- thailand.py파일 코드 ----------
class ThailandPackage:
    def detail(self):
        print("[태국 패키지 3박 5일] 방콕, 파타야 여행 (야시장 투어) 50만원")
-------- __init__.py파일 코드 ----------
__all__ = ["vietnam", "thailand"] # vietnam, thailand 모듈 공개
-------- prac.py파일 코드 ----------
from travel import *
trip_to = thailand.ThailandPackage()  #travel 생략
trip_to.detail()
 
# 꼭 파일 저장하기 

<모듈 직접호출, 외부호출 출력문> 
- 모듈을 테스트해보기 위해 모듈 파일내에서 직접호출 할 때 사용
__name__ : 파이썬에 내장된 특별한 변수 -> 현재 모듈의 이름을 나타냄
- 모듈이 직접 실행되는 경우에는 __name__변수 값이 __main__으로 설정

class VietnamPackage:
    def detail(self):
        print("[베트남 패키지 3박 5일] 다낭 효도 여행 60만원")


if __name__ == "__main__":    #
    print("이 문장은 모듈에서 직접호출 했을 때 출력됩니다.")
    trip = VietnamPackage()  #모듈객체 생성
    trip.detail()  #모듈 실행
else:
    print("외부에서 모듈이 호출되었습니다.")
 
출력
이 문장은 모듈에서 직접호출 했을 때 출력됩니다.
[베트남 패키지 3박 5일] 다낭 효도 여행 60만원
-------- prac.py파일 코드 ----------
from travel import *
trip_to = vietnam.VietnamPackage()  
trip_to.detail()

출력
외부에서 모듈이 호출되었습니다.
# [베트남 패키지 3박 5일] 다낭 효도 여행 60만원

<패키지, 모듈위치>
- 패키지나 모듈은 호출하려는 파일과 동일한 경로에 있거나 파이썬 라이브러리들이 들어있는 폴더에 있어야 사용 가느
- 아까 만들었던 모듈 파일들은 실행했던 파일과 같은 경로에 있었기 때문에 실행 가능
 => 그렇다면 만들었던 모듈들을 라이브러리들이 모인 파일로 이동시켜주면 호출파일과 경로가 달라도 실행 가능!!
- inspect 모듈을 import하고 getfile로 라이브러리 위치 파악

import inspect
import random
print(inspect.getfile(random))

C:\Users\user\AppData\Local\Programs\Python\Python39\lib\random.py #라이브러리 파일은 lib에 위치

-> 경로를 파악했으니 만들어둔 파일은 lib위치로 옮기면 끝임
*PyPI - 파이썬 라이브러리 사이트 

 

<외장함수, 내장함수>
* list of python builtins 구글링 -> 파이썬 docs에서 파이썬 인터프리터에서 쓸 수 있는 내장함수 리스트 볼 수 있음
* list of python modules (Python Moudle Index) 구글링 -> 외장함수 리스트

 

 

참고 - 나도코딩