Python __init__.py 역할과 활용 방법
Python 패키지의 __init__.py 파일의 역할과 다양한 활용 방법을 알아봅니다.
Python init.py 역할과 활용 방법
Python에서 __init__.py는 패키지를 정의하는 데 사용되는 특별한 파일입니다. 이 파일이 없으면 Python은 디렉토리를 일반 디렉토리로 인식합니다.
Environment
$ python --version
Python 3.11.5
$ ls -la mypackage/
__init__.py
core.py
utils.py
models/Problem: init.py 없이 패키지 구조 만들기
# __init__.py 없는 디렉토리 구조
$ mkdir -p testpackage/subpackage
$ echo "def hello(): print('Hello')" > testpackage/core.py
$ echo "x = 1" > testpackage/subpackage/data.py
$ python -c "from testpackage import core"
# ImportError: cannot import name 'core' from partially initialized moduleAnalysis: init.py의 역할
# __init__.py가 하는 일:
# 1. Python에게 이 디렉토리가 패키지임을 알림
# 2. 패키지 초기화 코드 실행
# 3. public 인터페이스 정의
# 4. __all__로 export 관리
# 빈 __init__.py도 패키지로 인식되게 함Solution: init.py 활용법
기본 패키지 구조
# mypackage/__init__.py
# This file makes 'mypackage' a package
print("mypackage initialized")
# mypackage/core.py
def process(data):
return data * 2
# Usage
$ python -c "from mypackage import core; print(core.process(5))"
mypackage initialized
10public 인터페이스 정의
# mypackage/__init__.py
from .core import process, validate
from .utils import format_date, parse_date
from .models import User, Product
__all__ = [
'process',
'validate',
'format_date',
'parse_date',
'User',
'Product',
]
__version__ = '1.0.0'
__author__ = 'Joel Park'Lazy Import 최적화
# mypackage/__init__.py
# Bad: Import everything at package load time
# from .heavy_module import HeavyClass # Slow!
# Good: Lazy import
def __getattr__(name):
if name == 'HeavyClass':
from .heavy_module import HeavyClass
return HeavyClass
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
# Usage - HeavyClass is only imported when accessed
from mypackage import HeavyClass # Import happens herePackage Configuration
# mypackage/__init__.py
import os
from pathlib import Path
# Package root directory
PACKAGE_ROOT = Path(__file__).parent
# Default configuration
DEFAULT_CONFIG = {
'debug': False,
'log_level': 'INFO',
'data_dir': PACKAGE_ROOT / 'data',
}
class Config:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._config = DEFAULT_CONFIG.copy()
return cls._instance
def get(self, key, default=None):
return self._config.get(key, default)
def set(self, key, value):
self._config[key] = value
# Singleton config instance
config = Config()Subpackage 구조
# mypackage/__init__.py
from .core import Core
from .utils import Helper
__all__ = ['Core', 'Helper']
# mypackage/core/__init__.py
from .engine import Engine
from .processor import Processor
__all__ = ['Engine', 'Processor']
# mypackage/core/engine.py
class Engine:
pass
# Usage
from mypackage.core import Engine
from mypackage import Core, HelperAdvanced: 동적 패키지 생성
#动态 패키지 생성
import importlib
import sys
def create_package(name, modules):
"""Create a package dynamically"""
import types
package = types.ModuleType(name)
package.__path__ = []
for module_name, module_code in modules.items():
module = types.ModuleType(f"{name}.{module_name}")
exec(module_code, module.__dict__)
setattr(package, module_name, module)
sys.modules[f"{name}.{module_name}"] = module
sys.modules[name] = package
return package
# Usage
my_package = create_package('dynamic_pkg', {
'utils': 'def helper(): return "Dynamic!"',
'data': 'value = 42'
})
print(my_package.utils.helper()) # Dynamic!
print(my_package.data.value) # 42Lessons Learned
패키지 식별:
__init__.py는 Python에게 해당 디렉토리가 패키지임을 알리는 역할을 합니다.Public API 관리:
__init__.py에서 import와__all__을 사용하여 패키지의 public API를 명확히 정의하세요.Lazy Import: 무거운 모듈은 필요한 시점에 임포트하여 패키지 로딩 시간을 줄일 수 있습니다.
초기화 코드: 패키지 레벨의 설정이나 초기화 코드를
__init__.py에 작성할 수 있습니다.Subpackage 구조: 복잡한 프로젝트에서는 하위 패키지를 만들고 각각의
__init__.py로 구조를 관리하세요.
This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.