TOP
class="layout-aside-left paging-number">
본문 바로가기
[파이썬 Projects]/<파이썬 기초>

[파이썬] 파이썬 기초: 패키지

by 기록자_Recordian 2024. 10. 16.
728x90
반응형
패키지(package)

 

패키지는 도트(.)를 사용하여 파이썬 모듈을 계층적으로 관리할 수 있게 해준다.

예. A.B: A-패키지 이름, B- A 패키지의 B 모듈

 

파이썬 패키지는 디렉터리와 파이썬 모듈로 이루어진다.

 

- game, sound, graphic, play : 디렉터리 이름

- 확장자가 .py인 파일: 파이썬 모듈

- game 디렉터리: 이 패키지의 루트 디렉터리

- sound, graphic, play : 서브 디렉터리

 

※ 루트 디렉터리: 컴퓨터 파일 시스템에서 계층 구조의 첫번째 또는 최상위 디렉토리

※ 서브 디렉터리: 루트 밑에 속하는 모든 서브 디렉토리는 자신과 부모, 자식 디렉토리의 관계를 형성.

 

 

 

 

디렉터리는 나무(Tree)구조를 가진다. 나무구조란 나무의 큰 줄기에서 작은 줄기가 뻗어나오고 그 줄기에서 다시 작은 줄기들이 뻗어나오는 것과 비슷하다 해서 붙여진 이름이다.

나무구조인 디렉터리 구조는 디렉토리 사이의 종속관계를 형성한다. 하위 디렉터리는 상위 디렉터리에 종속되며, 또한 상위 디렉터리가 삭제되면 하위 디렉터리도 자동적으로 삭제되는 운명을 가진다.

 


패키지 만들기

 

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

특정 디렉터리 밑에 game 및 기타 서브 디렉터리를 생성하고 .py 파일들을 만든다.

(필자의 경우는 C:\User...\Do_it_PY\package 에 생성할 예정)

1) 해당 디렉터리에 'game' 폴더를 생성하고 그 폴더 내에 sound 와 graphic 폴더를 생성한다.

 

2) 그리고 각 서브 디렉터리 내에 아래와 같은 모듈(.py 파일)을 만든다.

 

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

 

4) echo.py 파일은 다음과 같이 만든다.

def echo_test():
    print("echo")

 

5) render.py 파일은 다음과 같이 만든다

def render_test():
    print("render")

 

6) game 패키지를 참조할 수 있도록 명령 프롬프트 창에서 set 명령어로 PYTHONPATH 환경변수에 디렉터리를 추가한다.

그리고 파이썬 인터프리터를 실행한다.

set PYTHONPATH=추가할 디렉터리
python


2. 패키지 안의 함수 실행하기

패키지를 사용하여 echo.py 파일의 echo_test 함수를 실행해 본다.

 

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

 

[함수 실행 방법 -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()

 

★ import game 을 수행하면 game 디렉터리의 모듈 또는 game 디렉터리의 __init__.py 에 정의한 것만 참조할 수 있기 때문에 아래와 같이 echo_test 함수를 사용하는 것은 불가능하다.

import game
game.sound.echo.echo_test()

 

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

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_test'; 'game.sound.echo' is not a package

 


__init__py 의 용도

 

__init__.py 파일은 해당 디렉터리가 패키지의 일부임을 알려주는 역할을 한다. 만약 game, sound, graphic 등 패키지에 포함된 디렉터리에 __init__.py 파일이 없다면 패키지로 인식되지 않는다.

(python 3.3 버전부터는 __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

game.sound 패키지에서 모든 것(*)을 import 하였는데 echo 라는 이름이 정의되지 않았다는 이름 오류가 발생한다.

 

이렇게 특정 디렉터리의 모듈을 *를 사용하여 import 할 때에는 아래와 같이 해당 디렉터리의 __init__.py 파일에 __all__ 변수를 설정하고 import 할 수 있는 모듈을 정의해 줘야 한다.

__all__ = ['echo']

 

__init__.py 파일을 변경한 후 다시 수행해보면 결과가 잘 출력된다.

from game.sound import *
echo.echo_test()

 

마찬가지로, graphic\__init__,py 파일에도 __all__ = ['render'] 를 추가한 뒤,

__all__ = ['render']

 

하단의 명령어를 실행 해보면

from game.graphic import *
render.render_test()

 

결과가 잘 나오는 것을 확인할 수 있다.


relative 패키지

 

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

아래와 같이 render.py를 수정하면 된다.

from game.sound.echo import echo_test
def render_test():
    print("render")
    echo_test()

from game.sound.echo import echo_test 문장을 추가하여 echo_test 함수를 사용할 수 있도록 수정했다.

 

이후 아래의 명령어를 입력해보면

from game.graphic.render import render_test
render_test()

echo.py 모듈의 echo_test 함수가 잘 수행되는 것을 확인할 수 있다.

 

물론, 위 처럼 전체 경로를 사용하여 import 할 수도 있지만 아래와 같이 relative 하게 import 하는 것도 가능하다.

from ..sound.echo import echo_test

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

from ..sound.echo import echo_test 중 '..'는 부모 디렉터리를 의미한다.

graphic과 sound 디렉터리는 동일한 깊이 이므로 부모 디렉터리 (..)를 사용하여 위와 같은 import 가 가능하다.

잘 수행된다

 

.. 과 같은 relative 한 접근자는 render.py 처럼 모듈 안에서만 사용해야 한다.


[출처]

점프 투 파이썬, 이지스 퍼블리싱, 박응용

위키백과

IT 문화원

728x90
반응형