Module
Module은 변수/함수/클래스를 모아 놓은 python 파일을 의미한다.
# module1.py
def double_num(a):
return a * 2
def add_num(a, b):
return a + b
위 module1.py처럼 간단하게 저장해도 module이다!
Module을 불러오려면 import 명령어를 사용해야 한다. 중요한 점은 현재로서는 반드시 module1.py와 같은 directory로 이동해야 한다. (뒤에 다른 directory에서도 import하는 방법을 적어놓았다.)
import module1
module1.add_num(2, 3) # 5
module 전체를 import하면 module 이름 뒤에 .을 붙이고 가져와야 한다.
from module1 import double_num, add_num
double_num(3) # 6
module에서 특정 함수/변수/클래스만을 가져오면 module 이름 없이 바로 사용할 수 있다.
from module1 import *
*을 사용하면 module의 모든 함수/변수/클래스를 가져와서 사용할 수 있다. (__all__ list로 제어 가능)
cf) 다른 directory에서 import하는 방법
1) sys.path.append
import sys
print(sys.path)
['', 'C:\\Python312\\python312.zip', 'C:\\Python312\\DLLs', 'C:\\Python312\\Lib', 'C:\\Python312', 'C:\\Python312\\Lib\\site-packages']
위 코드와 같이 sys.path를 출력해보면 python library가 설치된 경로를 확인할 수 있다. (''는 현재 파일의 directory)
sys.path는 python에서 module과 package의 경로를 찾는 list이다. 찾는 순서는 다음과 같다.
- ' ': 최초 실행 파일의 directory가 자동으로 추가됨
- /usr/lib/python3.x: 표준 라이브러리 경로
- /usr/local/lib/python3.x/site-packages: 외부 라이브러리 경로 (pip install로 설치)
- PYTHONPATH: python 환경변수에 추가된 경로
- custom 설정 경로
sys.path.append를 사용하여 module의 directory를 추가하면 import가 가능하다!
하지만 이는 일시적으로, python session이 종료되면 유지되지 않는다. 즉, python을 종료하고 다시 실행하면 사라짐
영구적으로 추가하기 위해서는 아래와 같이 환경변수를 설정해야 한다.
2) PYTHONPATH
Python이 module을 검색할 때 추가로 찾는 환경변수, PYTHONPATH를 설정하면 Python 실행 시 자동으로 sys.path 앞쪽에 추가된다. (특정 경로의 module을 먼저 찾도록 강제 가)
import os
print(os.environ.get('PYTHONPATH'))
일시적으로 추가하기
Bash(Linux/macOS)/Powershell
export PYTHONPATH="/my/custom/path:/another/path"
# 여러개의 경로는 : 로 구분하여 추가한다.
CMD
set PYTHONPATH=C:\my\custom\path;C:\another\path
영구적으로 추가하기
Bash(Linux/macOS)
echo 'export PYTHONPATH="/my/custom/path:/another/path"' >> ~/.bashrc
source ~/.bashrc
Windows (환경 변수 설정)
시스템 환경 변수에 PYTHONPATH 추가
- 일회성 경로 추가 → sys.path.append()
- 자주 쓰는 경로 등록 → PYTHONPATH 설정 (환경 변수)
Package
Package는 여러 module을 묶어서 관리하는 방식
Python에서는 __init__.py 파일이 있으면 해당 폴더를 패키지로 인식한다.
* Python 3.3+에서는 __init__.py가 없어도 되지만 명확성을 위해 만드는 경우가 많다.
(즉, 같은 directory의 파일은 자동으로 import가 가능하다.)
my_project/
├── my_package/
│ ├── module1.py
│ ├── module2.py
└── main.py
main.py에서 module1을 import하려면 my_package를 패키지로 인식해야 한다. (__init__.py 추가)
my_package/
├── __init__.py
├── module1.py
├── module2.py
위와 같은 폴더 구조에서는 my_package가 package로 인식되어 아래와 같이 import가 가능하다.
import my_package.module1
from my_package import module2
cf) __init__.py에서는 패키지 초기화 시 동작을 정의할 수 있음
1) 초기 설정
# my_package/__init__.py
import os
CONFIG = {
"debug": os.getenv("DEBUG", False)
}
위와 같이 작성하면, package를 import만 config가 자동으로 설정된다.
2) __all__
from my_package import *에서 가져올 함수를 미리 정의
# my_package/__init__.py
__all__ = ['module1', 'module2']
위와 같이 작성하면 *에서 module1과 module2만 import 된다.
3) __init__.py 내부에서 import
my_project/
├── my_package/
│ ├── __init__.py
│ ├── module1.py
│ ├── module2.py
└── main.py
위 폴더 구조에서 __init__.py에 function을 import하면
# my_package/__init__.py
from .module1 import function1
from .module2 import function2
아래와 같이 개별 module을 import할 필요가 없어진다.
# main.py
import my_package
my_package.function1() # module1.py의 function1 호출
my_package.function2() # module2.py의 function2 호출
* __init__.py 내부에서 import를 하면 my_package의 namespace에 function1, function2가 추가되기 때문!
__init__.py에서 import하는 장점
- 패키지를 더 직관적으로 사용 가능
- 모듈 import할 필요 없음
- 서브모듈을 은닉할 수 있음
import
절대 경로 import
Root directory를 기준으로 전체 경로를 명시
Root directory: Python이 실행될 때 sys.path에 포함되는 최상위 directory (sys.path[0])
sys.path[0]가 결정되는 방식
- python script.py: script.py가 위치한 디렉토리
- python -m package.module: 패키지의 부모 디렉토리
- python (인터프리터 실행): 현재 작업 디렉토리 (os.getcwd())
- Jupyter Notebook 실행: Jupyter 서버의 실행 디렉토리 (예측 불가능)
from my_package.module1 import some_function
some_function()
- 명확성이 높음
- Directory 구조가 변경되어도 안정적
상대 경로 import
현재 module이 속한 package의 경로를 기준으로 import
from .module1 import some_function # 같은 패키지 내에서 import
from ..subpackage import another_function # 상위 패키지 import
- 패키지 내부에서만 사용 (Python의 상대경로 import는 패키지 내부 동작을 전제로 함)
- 스크립트 파일에서 직접 사용할 수 없음
스크립트 파일은 패키지의 일부로 인식되지 않음
스크립트 파일을 실행하면 해당 파일의 directory가 sys.path에 들어가지만, package로 인식되지 않아 package의 root directory (package context)는 sys.path에 들어가지 않는다.
cf) 절대 경로 vs 상대 경로 import
my_project/ ← 프로젝트 최상위 디렉토리
├── main.py ← 실행 파일
├── my_package/ ← 패키지
│ ├── __init__.py
│ ├── module1.py
│ ├── module2.py
│ ├── subpackage/ ← 하위 패키지
│ │ ├── __init__.py
│ │ ├── module3.py
│ │ ├── module4.py
- 절대경로 import: my_project 기준
- 상대경로 import: package 내부에서 import (현재 모듈이 패키지 내부에 있는 경우만 동작)
module1에서 module2를 import: my_package 기준
module3에서 module1을 import: 상위 package (my_package) 기준
pip install -e .
현재 directory에 있는 패키지를 개발 모드 (editable mode)로 설치
- pip install로 설치한 패키지는 변경이 불가능
- 매번 package를 새로 설치하지 않고, 코드가 변경되면 바로 반영됨
- 현재 dirctory의 setup.py, pyproject.toml를 분석하여 패키지 설치 (setup.py 또는 pyproject.toml이 필수)
디버깅 중인 패키지를 사용하거나, 코드를 변경할 필요가 있을 때 편리하다!
'코딩' 카테고리의 다른 글
[Python] Magic method 이해하기 (0) | 2025.01.26 |
---|