[Python] 패키지

ㅎㅎ·2021년 5월 23일
0

Python

목록 보기
18/27




📌 패키지(packages)

  • 패키지(packages)는 .(닷)을 사용해 파이썬 모듈을 계층적(디렉토리 구조)로 관리할 수 있게 해준다. 예를들어 모듈 이름이 a.b라면 a는 패키지 이름, b는 a패키지의 b모듈이 된다.
  • 즉, 파이썬 패키지는 디렉토리와 파이썬 모듈로 이루어져있다.
  • 간단한 파이썬 프로그램이 아닌 이상 밑 예시처럼 패키지 구조로 파이썬 프로그램을 만드는 것이 공동 작업이나 유지보수 등에서 유리하다. 또한 패키지 구조로 모듈을 만들면 다른 모듈과 이름이 겹쳐도 안전하게 사용할 수 있다.
  • ex) 가상의 game 패키지
game/
    __init__.py
    sound/
        __init__.py
        echo.py
        wav.py
    graphic/
        __init__.py
        screen.py
        render.py
    play/
        __init__.py
        run.py
        test.py

➡️ game, sound, graphic,play는 디렉토리 이름이고, 확장자가 .py인 파일은 파이썬 모듈이다. game 디렉토리가 이 패키지의 루트 디렉토리이고, sound,graphic,play는 서브 디렉토리이다.

- 패키지 만들기

  • 패키지 기본 구성 요소 준비하기
  1. 디렉토리 밑에 game 및 기타 서브 디렉토리를 생성한다. (디렉토리 잘 확인하기)
C:/doit/game/__init__.py
C:/doit/game/sound/__init__.py
C:/doit/game/sound/echo.py
C:/doit/game/graphic/__init__.py
C:/doit/game/graphic/render.py
  1. 각 디렉토리에 __init__.py파일을 만들고 내용은 비운다.
  2. echo.py,render.py를 각 각 만든다.
#echo.py
def echo_test():
    print ("echo")
    
#render.py
def render_test():
    print ("render")
  1. game패키지를 참조할 수 있도록 export(set) 명령어로 PYTHONPATH 환경 변수에 경로를 추가한다(C:/doit). 그리고 파이썬 인터프리터 셸을 실행한다. (이때 반드시 명령 프롬프트에서 파이선 인터프리터를 실행해야한다. 비주얼 스튜디오의 파이썬 쉘 아님)


- 패키지 안의 함수 실행하기

  • 이제 패키지를 사용해 echo.py 파일의 echo.test함수를 실행해보자. 이때 패키지 안의 함수를 실행하는 3가지 방법이 있다. 예제는 import 예제이므로 하나의 예제를 실행하면 종료(ctrl+z)하고 다시 실행해야한다. 경로 잘 확인하기

1. ehco 모듈을 import해 실행하기

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

2. echo 모듈이 있는 디렉토리까지를 from ... import해 실행하기

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

3. ehco모듈의 echo_test함수를 직접 import해 실행하기

>>> from game.sound.echo import echo_test
>>> echo_test()
echo
  • 그러나, 밑의 두가지 방법은 불가능하다.
# 불가능1 - import게임을 실행하면 game 디렉토리의 모듈 또는 game디렉토리의 __init__.py에 정의한 것만 참조할 수 있다.
>>> import game
>>> game.sound.echo.echo_test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'game' has no attribute 'sound'
>>>

#불가능2 - 도트(.)연산잘ㄹ 사용해 import를 할때는 import 가장 마지막 항목은 반드시 모듈 또는 패지키여야한다.
>>> import game.sound.echo.echo.test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'game.sound.echo.echo'; 'game.sound

- __init__.py

  • __init__.py파일은 해당 디렉토리가 패키지의 일부임을 알려주는 역할을 한다. 즉 game,sound,graphic 디렉토리에 __init__.py가 없다면 패키지로 인식되지 않는다. (python 3.3부터는 없어도 패키지로 인식하지만 하위 버전 호환을 위해 파일을 생성하는 것이 좋다.)
>>> from game.sound import *
>>> echo.echo_test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'echo' is not defined

➡️ game.sound 패키지에서 전체(*)를 import했는데 ehco 모듈이 정의되지 않았다는 오류가 떴다. 이렇게 특정 디렉토리의 모듈을 *를 시용해 import할때는 다음과 같이 디렉토리의 __init__.py 파일에 __all__변수를 설정하고 import할 수 있는 모듈을 정의해야한다.

__all__이 의미하는 것은 sound 디렉토리에서 *기호를 사용해 import 할 경우 이에 정의된 echo 모듈만 import된다는 의미이다.

# C:/doit/game/sound/__init__.py 파일안에 정의
__all__ = ['echo']
# 위 처럼 __init.py__파일을 변경한후 실행하면 결과가 정상적으로 출력된다. 
# 셸열때 경로 잘 확인하기. from game은 game이 포함되어있는 상위파일에서 열어야함.
>>> from game.sound import *
>>> echo.echo_test()
echo

- 주의해야할점

착각하지 않아야 할점은 from game.sound.echo import *__all__과 상관없이 무조건 import된다. 이렇게 __all__과 상관없이 무조건 import되는 경우는 from a.b.c import *에서 from의 마지막 항목인 c가 모듈인 경우이다.


- relative 패키지

  • 만약 graphic 디렉토리의 render.py모듈이 sound 디렉토리의 echo.py모듈을 사용하고 싶다면 render.py안에 echo.py경로를 추가해 주면 된다.
# 방법 1 - render.py
from game.sound.echo import echo_test #전체 경로 추가하기
def render_test():
    print ("render")
    echo_test()
    
# 방법 2 - render.py 
from ..sound.echo import 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(전체경로)
from ..sound.echo import echo_test(상대경로) 는 똑같은데 graphic과 sound 디렉토리가 같은 깊이의 디렉토리이므로 ..(부모 디렉토리)를 사용해 import를 가능하게 했다.

0개의 댓글