본문 바로가기
Programming/Python

[Python] 패키지(Packages) 만들기 / __init__.py / __all__ / 파이썬 relative 패키지

by EunjiBest 2022. 3. 7.

[Python] 패키지(Packages) 만들기 / __init__.py / __all__ / 파이썬 relative 패키지

 

 

 

패키지(Packages)

 

패키지는 . 을 사용해서 파이썬 모듈을 계층적으로 관리 할 수 있게한다.

 

A.B

 

A = 패키지의 이름

B = A패키지의 B 모듈

 

아래 가상의 게임패키지가있다.

 

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, paly 는 디렉터리 이름이고,

확장자가 .py인 파일은 파이썬 모듈이다.

 

루트 디렉토리 = game

서브 디렉토리 = sound, graphic, play 

 

파이썬으로 코딩을 할 때

간단한 프로젝트가 이니라면 이렇게 패키지 구조로 

코드를 짜는 것이 공동작업이나, 유지보수를 할 때 편리하다.

 

또한 패키지 구조로 모듈을 만들면 다른 모듈과 이름이 겹치더라도

안전하게 사용할 수 있는 것이 패키지의 장점이다.

 

 

 

만들기

 

1. C:doit 디렉터리 밑에 game 및 기타 서브 디렉터리생성.

 

C:/doit/game/__init__.py
C:/doit/sound/__init__.py
C:/doit/sound/echo.py
C:/doit/graphic/__init__.py
C:/doit/graphic/render.py

 

2. 각 디렉터리에 __init__.py 파일을 만들어 놓기만 하고 내용은 일단 비워둔다.

 

3. echo.py파일을 만들다.

 

#echo.py

def echo_test():
  print("echo")

 

4. render.py 파일을 만든다.

 

#render.py

def render_test():
  print("render")

 

5. 우리가 만든 game패키지를 참조할 수 있도록 명령 프롬포트에서 

set 명령어 PYTHONPATH 환경 변수에 C:\doit 디렉터리를 추가해준다.

그리고 파이썬 인터프리터(Interactive shell)을 실행해준다.

 

C:\>set PYTHONPATH=C:\doit
C:\>python

 

 

 

 

실행하기

 

echo.py 파일의 echo_test 함수를 실행해보자.

총 3가지의 방법이 있다.

 

 

1. echo모듈을 import하여 실행

 

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

 

 

 

2. echo모듈이 있는 디렉터리까지를 from ~ import 하여 실행

 

from game.sound import echo
echo.echo_test()

 

 

3. echo 모듈의 echo_test 함수를 직접 import하여 실행

 

from game.sound.echo import echo_test
echo_test()

 

 

 

주의 할 점

 

1.

 

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

Tradeback(most recent call last):
  File "<stdin>", line 1, in<module>
AttributeError: 'module'object has no attribute 'sound'

 

import를 game만 해두고

game.sound.echo.echo_test()로 함수를 불러 올 수 없다.

 

오류를 보면 sound 모듈이 안불러져 왔다고 뜬다.

 

 

2.

 

>>> import game.sound.echo.echo_test

Tradeback(most recent call last):
  File "<stdin>", line 1, in<module>
ImportError: No module named echo_test

. 연산자를 사용해서 import a.b.c처럼 import할 때

가장 마지막 항목인 c는 모듈 또는 패키지여야만 한다.

 

echo_test는 함수이기 때문에 모듈이 아니라는 오류가 뜨는 것을 볼 수 있다.

 

 

 

 

__init__.py

 __init__.py 파일은 해당 디렉터리가 패키지의 일부임을 알려주는 역할이다.

따라서 위에서 만든 게임 패키지를 예로 들었을 때

 

game, sound,graphic 등 패키지에 포함된 디렉터리에

__init__.py 파일이 없으면 패키지로 인식되지 않는다.

 

또한

 

from game.sound import *
echo.echo_test()

 

game.sound의 모든 것을 불러온다는 *을 이용해 코드를 치면

echo를 찾을 수 없다는 에러가 난다.

 

game.sound에 당연히 echo가 있어야하는데 왜 오류가 나는 것일까?

 

이렇게 특정 디렉터리의 모듈을 *을 사용해서 import할 때에는 

해당 디렉터리의 __init__.py 파일에 __all__이라는 변수를 설정해서

import할 수 있는 모듈을 정의해줘야한다.

 

 

C:/doit/game/sound/__init__.py
__all__ = ['echo']

 

__all__ = 

sound 디렉터리에서 * 기호를 사용하여

import를 할 경우 이 곳에 정의된 echo 모듈만

import된다는 의미이다.

 

 

 

 

 

relative 패키지

 

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

어떻게 해야할까.

 

앞서 만들었던 

render.py 파일을 수정해줘야한다.

 

#render.py

from game.sound.echo import echo_test

def render_test()
  print("render")
  echo_test()

 

from game.sound.echo import echo_test 문장을 추가하고

render_test함수 아래에 echo_test 함수를 넣어주면 된다.

 

 

하지만

from game.sound.echo import echo_test라고 전체 경로를 사용해서

import하는 것은 너무 길다.

 

따라서  ..을 이용하여 relative하게 import해준다.

 

#render.py

from ..sound.echo import echo_test

def render_test()
  print("render")
  echo_test()

 

from game.sound.echo import echo_test가

from ..sound.echo import echo_test로 변경되었다.

 

..은 부모 디렉토리 즉, game 디렉터리를 의미한다.

나머지 graphic과 sound 디렉터리는 동일한 깊이에 있으로

..만을 이용해서 import가 가능한 것이다.

 

주의할 점은

relative한 ..접근자는 render.py처럼 모듈 안에서만 사용이 가능한다.

일반 파이썬 인터프리터에서 relative한 접근자를 사용하면 오류가 난다.

 

 

 

 

 

 

 

 

 

 

이 글은 '점프 투 파이썬' 책을 참고한 포스팅입니다.

 

 

 

반응형

댓글