본문 바로가기

Programming/Python

3. Python _ 모듈, 패키지, 예외처리, 내장함수 _ Module, Packages, try exception

이 포스팅은 '점프 투 파이썬'을 다시 정독하면서 파이썬의 기초적이지만 매번 찾아보거나 몰랐던 부분을 정리하기 위한 목적으로 작성되었습니다.

Module 모듈
모듈: 함수나 변수 또는 클래스 들을 모아 놓은 파일로 다른 파이썬 프로그램에서 불러와 사용할 수 있게끔 만들어진 것.

import 모듈이름 을 통해서 불러온다.
ex) mod1.py를 불러오고 싶으면 import mod1이라고 한 뒤, mod1.sum으로 도트 연산자를 붙여서 사용한다.

from 모듈이름 import 모듈함수로 호출도 가능.
이 경우에는 그냥 바로 함수를 사용가능하다. ex) from mod1 import sum 혹은 import *(전부 다)

if __name__ == "__main__": 의 의미.
간단히 말해 파일을 직접 실행시킬 때만 수행되는 명령들을 뜻한다.
직접 python mod1.py 실행 시 __name__ == "__main__"이 참이 되어 해당 조건문 내에 명령어들이 수행되지만,
대화형 인터프리터나 다른 파일에서 이 모듈 호출 시에 거짓이 되어 해당 명령어들이 수행되지 않는다.
이는 단지 import하는 것만으로 파일이 전체 실행되는 것을 막아준다. 


Packages 패키지 
Packages: 도트(.)을 활용하여 파이썬 모듈을 계층적(디렉터리 구조)로 관리할 수 있게 해준다.
ex) A.B -> A라는 패키지의 B라는 모듈이란 뜻.

game이라는 디렉토리 안에 sound라는 디렉토리 안에 echo라는 파이썬 실행파일 속 정의 된 echo_test() 함수를 실행시켜보자.
import game.sound.echo
game.sound.echo.echo_test()와 같은 호출이 가능할 것이며

from game.sound.echo import echo_test
echo_test()와 같은 호출도 가능할 것이다.

__init__.py의 용도: 해당 디렉토리가 패키지의 일부임을 알려줌.
따라서 game, sound, echo 디렉토리를 패키지로 사용하기 위해서는 해당 디렉토리마다 __init__.py라는 파일이 있어야한다.

__all__ 의 용도
위의 패키지를 활용한 호출에서 만약 *을 써서 호출한다면 어떻게 될까?
from game.sound import*
echo.echo_test()
name 'echo' is not defined라는 에러가 뜨게 된다.
이는 from의 마지막에 온 것이 모듈이 아닌 디렉토리이기 때문에 발생하는 에러로,
해당 디렉토리 즉 sound의 __init__.py에 __all__ 이라는 변수가 설정되어 있지 않기 때문이다.
이럴 경우 __init__.py 안에 __all__ = ['echo']라는 변수를 설정해주면 된다.

relative 패키지
같은 경로의 모듈을 import할 때 ..과 같은  relative 접근자를 사용할 수 있다.
이는 인터프리터가 아닌 모듈 안에서 사용하여야 한다.
ex) from game.sound.echo import echo_test 대신에 from ..sound.echo import echo_test로 쓸 수 있다.
이는 전체 경로가 매우 긴 경우에 매우 유용하게 사용된다.


예외처리 try, except
list out of index나 No such file 혹은 division by zero등 무수히 많은 에러들, 하지만 이런 오류가 발생할 때 파이썬은 프로그램을 중단한다.
하지만 우리는 그것을 원하지 않을 수 있다.
이것은 지금 내가 점프 투 파이썬을 다시 정독하며 기본부터 다져야겠다고 생각하게 된 계기가 된 부분으로, 실제 실험이나 실무에 매우 중요하게 사용된다.
ex) 시리얼 통신을 하며 값을 계속 읽고 저장하여야 하는데, 잠시 연결이 끊겼다고 저장하던 프로그램이 중단되고 다시 연결 된 이후의 값들을 저장하지 않게 된다면 낭패이지 않을까? (실제 이번에 진행한 실험에서 그런 경우가 있었다.)

try, except 문
try 블록 수행 중 오류가 발생하면 except 블록이 수행됨.
try: ... except[발생 오류[as 오류 메시지 변수]] ... 와 같음. []는 생략가능하다는 뜻이다.

1. 오류 종류와 상관없이 오류만 발생하면 except 블록 수행
 try: ... except: ...

2. 발생 오류만 포함한 except문
try: ... except 발생 오류: ...

3. 발생 오류와 오류 메시지 변수까지 포함한 except문
try: ... except 발생 오류 as 오류 메시지 변수: ...

3번의 예시를 보자

try:
    4/0
except ZeroDivisionError as e:
    print(e)
>>> division by zero


try .. else 문
try문은 else절을 지원한다. else절은 예외가 발생하지 않은 경우 실행되며 except절 바로 다음에 위치하여야 한다.

try .. finally 문
finally절은 예외 발생 여부에 상관없이 항상 수행되며 파일을 쓰기모드로 연 경우 f.close() 등으로 닫을 때 사용할 수 있다.

오류 회피하기
오류가 발생할 경우 pass를 사용하여 오류를 그냥 회피하도록 할 수도 있다.

종합예제는 아래와 같다.

try:
    f = open('jiwan.txt','w')
except FileNotFoundError as e:
	print(str(e))
	#pass 를 쓰면 그냥 넘어감.
else:
	data = f.read()
finally:
	f.close()

raise를 통해 일부러 오류를 발생시킬수도 있다. (ex. 반드시 함수가 실행되어야 하도록 만들 때)