파이썬에서 코드를 작성하기 이전에 작업에 필요한 모듈이나 패키지를 불러오기 위해서 import 구문을 사용한다.
파이썬 인터프리터는 어떻게 해당 모듈 혹은 패키지를 찾아오는 것일까?
Import 구문을 실행하였을 때, 파이썬에서 모듈과 패키지를 찾는 순서가 정해져 있다.
각각에 대해서 알아보자.
docs를 보면 이미 불러온 모듈이나 패키지를 딕셔너리 형태로 저장한다고 되어있다. 즉, 모듈/패키지를 import 할 때 가장 먼저 확인하는 것은 이미 불러온 것인지를 보는 것이다.
sys.modules에 전에 불러왔던 모듈/패키지를 저장해놓기 때문에, 다시 불러올 때 로딩 시간을 단축할 수 있다. 다만, 당연히 새롭게 import 하는 경우에는 해당 딕셔너리에 저장되어 있지 않다.
파이썬에서 제공하는 파이썬 공식 라이브러리들이다. 파이썬 안에 포함되어 있으므로 바로 찾아낼 수 있다.
import sys
print(sys.builtin_module_names)
위와 같이 sys.builtin_module_names
를 출력하면 어떤 모듈이 파이썬에 내장되어 있는지 확인할 수 있다.
해당 builtin_module_names를 프린트하기 위해 import 한 sys 모듈도 파이썬의 built-in module 에 포함된다.
마지막으로 sys.path에 있는 경로들을 확인한다.
import sys
print(sys.path)
sys.path를 출력해보면 리스트 형태로 나타난다. 첫번째부터 순서대로 해당 디렉토리를 확인한다. sys.path는 string 혹은 bytes 타입으로 추가할 수 있다.
주로 local 에서 직접 작성한 모듈을 불러오기 위해 해당 모듈이 위치한 경로를 sys.path에 추가하는 방식으로 이용한다.
위의 sys.modules, built-in modules, sys.path 를 찾아보고 없는 경우에는 에러를 리턴한다.
그럼 sys 모듈은 어찌 찾는가?
: 위에서 봤듯이 sys 모듈은 built-in module 이므로 경로에 대한 문제가 발생하지 않는다.
sys.path 경로와 관련하여 하나 더 짚고 넘어갈 것이 있다.
경로를 지정하는 방식은 크게 절대경로
와 상대경로
로 나뉜다.
절대경로는 말그대로 절대적이다. 원하는 모듈이나 패키지의 경로를 절대경로로 지정해주면 어떤 스크립트에서든 문제없이 import 할 수 있다. 경로를 최상단 디렉토리를 기준으로 지정한다.
반면 상대경로는 현재 import 하는 스크립트를 기준으로 상대적인 경로를 지정한다. 따라서 절대경로에 비해 상대적으로 경로의 길이가 짧게 표현된다는 장점이 있다. 반면 스크립트에 따라서 경로가 바뀐다는 단점도 있다.
아래의 예시를 통해 살펴보자.
my_app 이라는 이름의 최상단 프로젝트 디렉토리가 있다.
를 import 한다고 가정하자.
현재 코드를 실행하는 스크립트는 package2 의 module4.py 이다.
# package2/module4.py
# 절대경로
from module3 import func1
from subpackage1 import module5
# 상대경로
from .module3 import func1
from .subpackage import module5
상대경로가 절대경로보다 짧고 간단하게 표현된다. 최상위 my_app 프로젝트 디렉토리와 하위 package2는 현재 스크립트를 실행하는 module4.py 의 current directory 로 sys.path 에 default로 포함되므로 굳이 지정해줄 필요가 없다. 절대경로는 바로 이 current directory에서 시작한다.
경로의 복잡도, 코드의 가독성 혹은 파일의 위치가 자주 변화하는가 등을 판단하여 절대경로를 지정할 것인지 상대경로를 지정할 것인지 판단해야 한다.
closure : 부모 함수 안에 포함된 자식함수
decorator: 함수를 꾸며주는 역할을 함
def decorator(func):
def wrapper():
실행문
return 결과
return wrapper
@decorator()
def func():
실행문
def decorator(parameter):
def real_decorator(func):
def wrapper():
실행문
return 결과
return wrapper
return real_decorator
@decorator(parameter)
def func():
실행문
def decorator(func):
def wrapper(*args, **kargs):
실행문
return 결과
return wrapper
@decorator
def func(a,b):
실행문
class Trace:
def __init__(self,x): # decorator 에 parameter 있는 경우
self.x = x # parameter 없는 경우는 함수로 받음
def __call__(self,func): # decorator에 parameter 없는 경우에는 실행 함수의 인자를 받음
def wrapper(*args,**kargs):
실행문
return 결과
return wrapper
@Trace(x)
def func(a,b):
실행문
return 결과
scope : 변수나 함수, 객체가 유효한 범위
local < enclosing < module < built-in
shadowing
효과가 나타남class
__init__
메소드가 자동으로 호출됨모듈과 패키지
패키지 초기화
__init__.py
로 패키지 초기 설정 가능함__init__.py
자동 실행됨__init__.py
역할import pkg.mod1
pkg.mod1.func2()
이 경우, __init__.py
에서 먼저 import 해 놓으면 함수명만 불러올 수 있음
# __init__.py
from .mod1 import func2
# main.py
from pkg import func2
fun2()
# __init__.py
from .mod1 import fun2
from .mod2 import fun3
__all__ = [“func2”,”func3”] #__all__ 의 default는 모든 변수임
# main.py
from pkg import *
func2()
func3()
func4() # error