파이썬 모듈과 패키지 이해하기

모듈

프로그램이 복잡해질 때, 서로 다른 기능을 가진 부분들을 분리하여 각각의 .py 스크립트로 만드는 것이 유용합니다. 이 방식의 장점은 다음과 같습니다:

  • 각 모듈이 다른 부분을 담당하므로 논리가 더 명확해집니다.
  • 공통된 코드를 재사용할 수 있습니다.
  • 각 모듈은 독립적인 네임스페이스를 가지므로 같은 이름의 변수/함수/클래스를 사용할 수 있습니다.

Python에서 .py 파일 하나가 바로 모듈입니다

모듈 임포트

모듈은 다른 모듈을 임포트할 수 있으며, 주요한 방법은 다음과 같습니다:

import 모듈명

예를 들어 import time와 같이 모듈을 임포트하면, 해당 모듈의 이름으로 함수에 접근할 수 있습니다(time.sleep(1)).

주의: import 문을 사용할 때는 최소한 모듈 단위로 임포트해야 합니다. 예를 들어 import time.sleep은 잘못된 표현이며, 특정 함수를 임포트하려면 from ... import ... 구문을 사용해야 합니다.

from 모듈명 import ...

특정 변수/함수/클래스만 임포트하는 방법입니다: 예를 들어 from time import localtime, sleeplocaltime, sleep 함수를 현재 네임스페이스로 가져옵니다. 이렇게 하면 sleep(1)처럼 직접 호출할 수 있습니다.

# 개별 임포트
from time import localtime
from time import sleep

# 한 줄로 여러 항목 임포트
from time import localtime, sleep

# 괄호 안에서 여러 항목 임포트
from time import (localtime, 
                  sleep)

부분 임포트 대신 time.sleep(1)과 같이 모듈 이름을 함께 사용하면 출처가 명확해집니다.

from 모듈명 import *

from time import *와 같이 모든 변수/함수/클래스를 임포트할 수 있습니다. 그러나 _로 시작하는 항목은 제외됩니다. 또한 __all__ 변수를 설정하여 임포트할 항목을 제한할 수 있습니다.

# b.py 내용
__all__ = ['b', 'c']  # 'from b import *' 시 b와 c만 임포트됨

b = 1
_b = 2  # _로 시작하는 변수는 비공개 변수로 간주됨
c = 3
d = 4
# a.py 내용
from b import *

c = 4  # b에서 임포트한 c를 덮어씀
print(b)
print(c)
# print(d)  # d는 임포트되지 않았으므로 오류 발생

이 방식은 권장되지 않으며, 잠재적인 이름 충돌과 출처 불명확성 문제를 일으킬 수 있습니다.

임포트 및 별칭 설정

다음과 같이 임포트 시 별칭을 설정할 수 있습니다:

from time import sleep as wait  # 별칭 wait로 임포트
wait(1)

모듈 임포트 관련 주요 문제

메인 모듈과 임포트 모듈

현재 실행 중인 모듈은 메인 모듈이며, 나머지는 임포트 모듈로 간주됩니다. Python의 특수 변수 __name__을 사용하여 현재 모듈이 메인 모듈인지 확인할 수 있습니다.

# b.py 내용
print('b 모듈, 현재 모듈명:', __name__)

if __name__ == '__main__':
    print('메인 코드 - b 모듈만 실행시 출력')
# a.py 내용
import b
print('a 모듈, 현재 모듈명:', __name__)

실행 결과:

b 모듈, 현재 모듈명: b
a 모듈, 현재 모듈명: __main__

메인 모듈에서만 실행되는 코드는 if __name__ == '__main__': 블록에 작성됩니다.

모듈 임포트 경로

모듈 임포트 시 검색 경로는 다음과 같습니다:

  • 실행 스크립트의 디렉토리
  • PYTHONPATH 환경 변수로 설정된 디렉토리
  • Python의 사이트 패키지 디렉토리

찾지 못하면 ModuleNotFoundError가 발생합니다.

순환 임포트 문제

순환 임포트는 a 모듈이 b 모듈을 임포트하고, b 모듈이 다시 a 모듈을 임포트하는 경우입니다. import 모듈명 방식은 순환 임포트를 허용하지만, from ... import ... 방식은 문제가 생길 수 있습니다.

# c.py 내용
import b
var_c = 3
print('나는 c 모듈')

# b.py 내용
import c
var_b = 2
print('나는 b 모듈')

# a.py 내용
import a
var_a = 1
print('나는 a 모듈')

이 경우 import 방식은 정상 작동하지만, from ... import ... 방식은 에러가 발생할 수 있습니다.

패키지(Package)

여러 모듈을 관리하기 위해 패키지를 사용할 수 있습니다. Python에서는 디렉토리를 패키지로 간주하며, __init__.py 파일이 있을 필요는 없습니다.

패키지 초기화

패키지 내의 __init__.py 파일은 패키지 초기화 및 설정에 사용됩니다. 예를 들어, package/__init__.py에 다음과 같이 작성할 수 있습니다:

a = '변수 a'

이렇게 하면 from package import a를 통해 a 변수를 바로 사용할 수 있습니다.

또한 __init__.py에서 다른 모듈을 임포트하여 패키지의 인터페이스를 정의할 수 있습니다:

from . import a
from . import b
from .sub_package import c
from .a import var_a
from .b import var_b
from .sub_package.c import var_c

이제 from package import a, b, c, var_a, var_b, var_c와 같이 사용할 수 있습니다.

참고: Python 공식 문서 - 모듈에 대한 자세한 내용

태그: python 모듈 패키지 임포트 순환임포트

5월 21일 23:33에 게시됨