점프 투 파이썬 - 패키지
Language/Python

점프 투 파이썬 - 패키지

뉴비뉴 2019. 7. 15.

패키지란 무엇인가?

도트(.)를 사용하여 파이썬 모듈을 계층적(디렉터리 구조)으로 관리할 수 있게 해준다.

예를 들어 모듈 이름이 A.B 인 경우에 A는 패키지 이름이 되고 B는 A 패키지의 모듈이 된다.

(패키지 이름).(패키지 모듈)

패키지 만들기

패키지 기본 구성 요소 준비하기

1. C:/doit 디렉터리 밑에 game 및 기타 서브 디렉터리를 생성하고 .py 파일들을 다음과 같이 만들어 보자

# echo.py
def echo_test():
    print ("echo")
    
    
# render.py
def render_test():
    print ("render")

명령 프롬프트 창에서 set 명령어로 PYTHONPATH 환경변수에 C:/doit 디렉터리를 추가한다.

C:\> set PYTHONPATH=C:/doit
C:\> python
Type "help", "copyright", "credits" or "license" for more information.
>>>

패키지 안의 함수 실행하기

이제 패키지를 사용하여 echo.py 파일의 echo_test 함수를 실행해 보자. 패키지 안의 함수를 실행하는 방법은

다음 3가지가 있다. 다음 예제는 import 예제이므로 하나의 예제를 실행하고 나서 다음 예제를 실행할 때에는 반드시 인터프리터를 종료하고 다시 실행해야 한다. 인터프리터를 다시 시작하지 않을 경우 이전에 import 한 것들이 메모리에 남아 있어 엉뚱한 결과가 나올 수 있다.

 

첫 번째는 echo 모듈을 import 하여 실행하는 방법

>>> import game.sound.echo # game/sound/echo.py
>>> game.sound.echo.echo_test()
echo

두 번째는 echo 모듈이 있는 디렉터리까지를 from ... import 하여 실행하는 방법

>>> from game.sound import echo # from 에서 echo 모듈이 있는 디렉터리 까지 지정
>>> echo.echo_test()
echo

세 번째는 echo 모듈의 echo_test 함수를 직접 import 하여 실행하는 방법

>>> from game.sound.echo import echo_test
>>> echo_test()
echo

만약 같은 폴더 내에 있는 파일을 위 처럼 game.sound.echo 처럼 하기 싫다면 아래와 같이 사용할 수 있다.

>>> from . import render # . 을 줌으로써 다른 것들을 지정할 필요가 없다. import 에서는 모듈 또는 패키지
>>> render.render_test()
render

도트 연산자(.)를 사용해서 import a.b.c 처럼 import 할 때 가장 마지막 항목인 c는 반드시 모듈 또는 패키지여야 한다.

__init__.py 의 용도

__init__.py 파일은 해당 디렉터리가 패키지의 일부임을 알려주는 역할을 한다. 만약 game, sound, graphic 등

패키지에 포함된 디렉터리에 __init__py 파일이 없다면 패키지로 인식되지 않는다.

※ python3.3 버전부터는 __init__.py 파일이 없어도 패키지로 인식한다(PEP 420).
하지만 하위 버전 호환을 위해 __init__.py 파일을 생성하는 것이 안전한 방법이다.
>>> from game.sound import *
>>> echo.echo_test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'echo' is not defined

특정 디렉터리 모듈을 * 를 사용하여 import 할 때에는 다음과 같이 해당 디렉터리의 __init__.py 파일에

__all__ 변수를 설정하고 import 할 수 있는 모듈을 정의해 주어야 한다.

# C:/doit/game/sound/__init__.py
__all__ = ['echo']
※ 착각하기 쉬운데 from game.sound.echo import * 는 __all__과 상관없이 무조건 import된다.
이렇게 __all__과 상관없이 무조건 import되는 경우는 from a.b.c import * 에서 from의 마지막 항목인 
c가 모듈인 경우이다.

위와 같이 __init__.py 파일을 변경한 후 위 예제를 수행하면 원하던 결과가 출력되는 것을 확인할 수 있다.

relative 패키지

만약 graphic 디렉터리의 render.py 모듈이 sound 디렉터리의 echo.py 모듈을 사용하고 싶다면

다음과 같이 render.py 를 수정하면 가능하다.

from game.sound.echo import echo_test # echo_test 함수를 사용할 수 있게 추가
def render_test():
    print("render")
    echo_test()
>>> from game.graphic.render import render_test
>>> render_test()
render
echo

위 예제처럼 from game.sound.echo import echo_test 를 입력해 전체 경로를 사용하여 import할 수도 있지만

다음과 같이 relative 하게 import 하는 것도 가능하다.

from game.sound.echo import echo_test --> from ..sound.echo import echo_test 로 변경

! . . - 부모 디렉터리

! . - 현재 디렉터리

 

 

댓글

💲 추천 글