모듈
프로그램이 복잡해질 때, 서로 다른 기능을 가진 부분들을 분리하여 각각의 .py 스크립트로 만드는 것이 유용합니다. 이 방식의 장점은 다음과 같습니다:
- 각 모듈이 다른 부분을 담당하므로 논리가 더 명확해집니다.
- 공통된 코드를 재사용할 수 있습니다.
- 각 모듈은 독립적인 네임스페이스를 가지므로 같은 이름의 변수/함수/클래스를 사용할 수 있습니다.
Python에서 .py 파일 하나가 바로 모듈입니다
모듈 임포트
모듈은 다른 모듈을 임포트할 수 있으며, 주요한 방법은 다음과 같습니다:
import 모듈명
예를 들어 import time와 같이 모듈을 임포트하면, 해당 모듈의 이름으로 함수에 접근할 수 있습니다(time.sleep(1)).
주의:
import문을 사용할 때는 최소한 모듈 단위로 임포트해야 합니다. 예를 들어import time.sleep은 잘못된 표현이며, 특정 함수를 임포트하려면from ... import ...구문을 사용해야 합니다.
from 모듈명 import ...
특정 변수/함수/클래스만 임포트하는 방법입니다:
예를 들어 from time import localtime, sleep는 localtime, 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 공식 문서 - 모듈에 대한 자세한 내용