본문 바로가기

연구노트/Python

파이썬 패키지

 

파이썬 패키지

 

패키지란?

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

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

 

파이썬 패키지는 디렉터리와 파이썬 모듈로 이루어지며 구조는 아래와 같다.

game, sound, graphic, play는 디렉터리 이름이고 확장자가 .py인 파일은 파이썬 모듈이다.

##파이썬 패키지
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는 서브 디렉터리이다.

규모가 큰 파이썬 프로그램이라면 이렇게 패키지 구조로 파이썬 프로그램을 만드는 것이 공동 작업이나 유지 보수 등

여러 면에서 유리하다. 또한 패키지 이름이 겹치더라도 더 안전하게 사용할 수 있다.

 

패키지 만들기

 

이제 위 예제와 비슷한 game 패키지를 직접 만들어 보며 패키지를 이해해 보자.

 

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

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

##패키지 기본 구성 요소 준비하기
C:\ipmes1>game\__init__.py
C:\ipmes1>game\sound\__init__.py
C:\ipmes1>game\sound\echo.py
C:\ipmes1>game\graphic\__init__.py
C:\ipmes1>game\graphic\render.py
 

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

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

## echo 파일
# echo.py
def echo_test():
    print("echo")
 

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

## render 파일
# render.py
def render_test():
    print("render")
 

5. 다음 예제를 수행하기 전에 우리가 만든 game 패키지를 참조할 수 있도록 명령 프롬프트창에서 set 명령어로

PYTHONPATH 환경 변수에 C:\ipmes1 디렉터리를 추가한다. 그리고 파이썬 인터프리터를 실행한다.

## game 패키지 참조
PS C:\Users\itsteam> set PYTHONPATH=C:\ipmes1
PS C:\Users\itsteam> python
Python 3.13.2 (tags/v3.13.2:4f8bb39, Feb  4 2025, 15:23:48) [MSC v.1942 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
 

 

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

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

패키지 안의 함수를 실행하는 방법은 다음 3가지가 있다. 다음 예제는 import 예제이므로 하나의 예제를 실행하고 나서

다음 예제를 실행할 때에는 반드시 인터프리터를 종료하고 다시 실행해야 한다.

인터프리터를 다시 시작하지 않을 경우 이전에 import한 것들이 메모리에 남아 있어 예상치 못한 결과가 발생할 수 있다.

 

첫 번째는 echo 모듈을 import하여 실행하는 방법으로, 다음과 같이 실행한다.

## echo 모듈 실행1
import game.sound.echo
game.sound.echo.echo_test()
→ echo
 

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

## echo 모듈 실행2
from game.sound import echo
echo.echo_test()
→ echo
 

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

## echo 모듈 실행3
from game.sound.echo import echo_test
echo_test()
→ echo
 

 

하지만, 다음과 같이 echo_test 함수를 사용하는 것은 불가능 하다.

import game을 수행하면 game 디렉터리의 모듈 또는 game 디렉터리의 __init__.py에 정의한 것만 참조할 수 있다.

그래서 아래와 같이 실행 하였을때, 에러 코드를 반환한다.

## echo 모듈 실행 오류1
import game
game.sound.echo.echo_test
echo_test()
→ Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module'object has no attribute 'sound'
 

또 다음처럼 echo_test 함수를 사용하는 것도 불가능하다.

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

## echo 모듈 실행 오류2
import game.sound.echo.echo_test
→ Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named echo_test
 

 

__init__.py의 용도

 

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

만약 game, sound, graphic등 패키지에 포함된 디렉터리에 __init__.py 파일이 없다면 패키지로 인식되지 않는다.

다음을 따라 해 보자.

## __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 모듈을 사용할 수 있어야 할 것 같은데

echo라는 이름이 정의되지 않았다는 이름 오류가 발생했다.

 

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

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

## __all__ 설정
# C:/ipmes1/game/sound/__init__.py
__all__ = ['echo']
 

여기에서 __all__이 의미하는 것은 sound 디렉터리에서 * 기호를 사용하여 import할 경우 이곳에 정의된

echo 모듈만 import된다는 의미이다.

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

## __all__ 설정
# C:/ipmes1/game/sound/__init__.py
__all__ = ['echo']
 

 

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 문장을 추가하여 echo_test 함수를 사용할 수 있도록 수정했다.

이렇게 수정한 후 아래와 같이 실행해 보자.

## render.py 수정 실행
from game.graphic.render import render_test
render_test()
→ render
→ echo
 

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

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

## relative 활용하기
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로 변경되었다.

여기에서 ..은 상위 디렉터리를 의미한다.

graphic과 sound 디렉터리는 game 하위에 있는 동일한 레벨의 디렉터리이기 때문에

상위 디렉터리(..)를 사용하여 상위 디렉터리로 이동한 후, 다시 sound.echo 모듈로 접근할 수 있다.

 

..과 같은 relative한 접근자는 render.py처럼 모듈 안에서만 사용해야 한다. 파이썬 인터프리터 relative한 접근자를

사용하면 'SystemError : cannot perform relative import'오류가 발생한다.

 

모듈과 패키지를 찾는 경로

지금까지 모듈과 패키지는 현재 폴더(디렉터리)에 만들었다. 파이썬에서는 현재 폴더에 모듈, 패키지가 없으면

다음 경로에서 모듈, 패키지를 찾을 수 있다.

## 모듈, 패키지 찾는 경로
import sys
sys.path
['', 'C:\\Users\\ipmes\\AppData\\Local\\Programs\\Python\\Python313\\python313.zip',
 'C:\\Users\\ipmes\\AppData\\Local\\Programs\\Python\\Python313\\DLLs', 
'C:\\Users\\ipmes\\AppData\\Local\\Programs\\Python\\Python313\\Lib', 
'C:\\Users\\ipmes\\AppData\\Local\\Programs\\Python\\Python313', 
'C:\\Users\\ipmes\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages', 
'C:\\ipmes1']
 

sys 모듈의 path 변수에는 모듈, 패키지를 찾는 경로가 들어있다.

여기서 'site-packages' 폴더에는 pip로 설치한 패키지가 들어간다.

그리고 자기가 만든 모듈, 패키지도 site-packages 폴더에 넣으면 스크립트 파일이 어디에 있든 모듈, 패키지를 사용할 수 있다.

 

 

 

'연구노트 > Python' 카테고리의 다른 글

파이썬 내장 함수  (0) 2025.04.30
Python 예외 처리  (0) 2025.04.30
파이썬 모듈  (0) 2025.04.18
Python 클래스  (0) 2025.04.17
Python 파일 읽고 쓰기  (0) 2025.04.16