변수, 함수, 클래스 등을 모아 놓은 파일을 스크립트라고 한다. 우리가 cmd
같은 명령 프롬프트에서 python 파일명.py
같은 명령어로 파일을 실행하는 것을 '스크립트를 실행한다' 라고 말한다.
이렇게 하나의 스크립트로 프로젝트를 관리해도 되나, 유지보수를 쉽게 하기위해 여러 파일로 나눌 수 있다. 그리고 이렇게 나뉜 파일에 썼던 함수들을 다시 복사해서 사용하지 않고, 불러올 수 있는 파일을 모듈이라고 한다. 모듈은 다른 모듈을 불러올 수 있고, 모듈 밑에 서브 모듈이 있을 수 있다.
# File name : fibo.py
# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
이를 새로운 파일에 import fibo
를 한다고 해서 새 파일의 심볼 테이블에 값이 들어가진 않는다. 전역 변수 __name__
이 실행되면서 오직 모듈 이름만 들어갈 뿐이다.
>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
이렇게 모듈 이름을 사용해서 함수들에 접근할 수 있다. 만약 함수를 자주 사용할 것이라면 아래처럼 지역 변수로 정의하면 된다.
>>> fib = fibo.fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
각 모듈은 자신만의 심볼 테이블을 갖고 있는데, 그 모듈에서 정의된 함수들의 전역 심볼 테이블로 사용된다. 그렇기때문에 우리는 모듈을 사용할 때 우리가 작성한 전역 변수와 import
한 모듈의 전역변수가 충돌할 걱정을 안해도 된다. 만약, 사용자가 불러온 모듈의 전역 변수에 접근하고 싶으면 modulename.itemname
으로 할 수 있다.
모듈에 들어있는 함수를 직접 임포트 하는 방법은 아래와 같다.
>>> from fibo import fib, fib2
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
>>> fib.fib(500)
NameError: name 'fibo' is not defined
import fibo
를 하지 않았기때문에 심볼 테이블에는 fibo
가 아닌 fib
과 fib2
만 존재한다. 그래서 fibo
를 이용해 fib
을 불러오면 error
가 발생한다.
모듈에 정의된 모든 함수를 import
하는 방법도 있다.
>>> from fibo import *
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
함수 명이 밑줄_
로 시작되는 것을 제외한 모든 함수를 불러온다. 다만, 이러한 방법은 권장하지 않는데, 그 이유는 모듈의 함수명과 사용자의 변수명이 충돌 할 수 있기 때문이다. 그리고 또한, 가독성도 덜어지니 되도록 *
은 사용하지 말자.
as
는 길이가 긴 모듈 또는 함수명의 별칭을 지어주는 것이다. 만약, 모듈 또는 함수명의 길이가 엄청 길 경우 가독성도 떨어지고 코드를 작성하는 것에도 어려움이 클 것이다. 그래서 as
를 사용해서 별칭을 만든다.
# 모듈에 as를 사용한 경우
>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
# 함수에 as를 사용한 경우
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
python fibo.py
으로 실행을 하면 __name__
은 __main__
으로 설정 된다.
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
그래서 모듈 끝에 위 코드를 붙이면 모듈뿐만 아니라 스크립트로도 작동된다. 오직 모듈이 main
일 경우에만 동작되므로 import
하여 모듈을 사용될 때는 위 코드가 동작하지 않는다.
$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34
보통 모듈에 대한 사용자 인터페이스를 제공하거나 테스트 목적으로 사용된다.
파이썬에서 모듈을 불러오기 위해 해당 파일을 찾을 때 검색 순서는 아래와 같다.
- python 내장 모듈에서 검색
sys.path
에 담긴 디렉터리들에서 검색
그렇기 때문에 만약 python 내장 모듈과 같은 이름의 모듈을 생성해도 내장 모듈이 우선시되어 import
된다.
sys.path
에 담기는 디렉터리의 순서는 아래와 같다.
- 현재 실행 중인 python 코드를 포함하는 폴더
- 환경 변수에 정의된 모듈 검색 경로
import sys
print(sys.path)
['현재 실행 중인 python 코드를 포함하는 폴더`, `환경 변수에 정의된 경로`]
sys.path.append('C:\\')
print(sys.path)
['현재 실행 중인 python 코드를 포함하는 폴더`, `환경 변수에 정의된 경로`, 'C:\\']
그래서 위처럼 sys.path
에 경로를 추가할 수도 있다.
앞서 봤던 모듈의 집합을 의미한다. 즉, 패키지는 기능들이 모듈 여러개로 나누어져 있다. 패키지 이름의 폴더 안에 여러개의 모듈(.py)이 모여있는 구조이다. 패키지 또한 import
할 때 모듈과 마찬가지로 sys.path
에 있는 디렉터리들을 검색하면서 패키지를 찾는다. 파이썬이 일반 폴더와 패키지 폴더를 구분하기 위해 패키지 폴더에는 __init__.py
라는 파일이 필요하다. 이 파일이 있으면 파이썬은 해당 폴더가 패키지 폴더임을 인식한다. __init__.py
파일은 빈 파일이여도 상관없으며 초기화 코드를 실행할 수도 있다.
아래는 sound
패키지의 예이다.
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
#import item.subitem.subsubitem
import sound.effects.echo
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
#from package import item
from sound.effects import echo
echo.echofilter(input, output, delay=0.7, atten=4)
from sound.effects.echo import echofilter
echofilter(input, output, delay=0.7, atten=4)
sound
패키지 아래에 있는 effects
모듈 아래의 echo
모듈을 불러오는 코드이다. import
는 먼저 item
이 패키지에 정의 되어 있는지 검사하고, 없으면 모듈이라고 가정하고 다시 찾는다. 이때도 찾지 못하면 importError
를 출력한다.
import item.subitem.subsubitem
은 마지막을 제외하곤 항상 패키지와 모듈이여야한다. 마지막은 모듈 또는 클래스나 함수, 변수 등이 될 수 있다.
*
사용하기from sound.effects import *
을 사용하면 effects
아래의 모듈이 다 불러오지 않고 import sound.effects
를 사용한 것처럼 sound.effects
만 불러온다. 그래서 개발자가 직접 *
을 사용시 불러올 모듈을 정의할 수 있다.
# sound/effects/__init__.py
__all__ = ["echo", "surround", "reverse"]
sound/effects/__init__.py
에 위 코드를 담으면 from sound.effects import *
을 사용하면 세 모듈만 import
된다.
이웃 패키지의 서브 모듈을 import
할 수 있는 방법은 크게 절대 경로와 상대 경로 두 가지가 있다.
sound.filters.vocoder
모듈이 sound.effects
패키지의 echo
모듈이 필요하다면, from sound.effects import echo
처럼 절대 경로를 사용하면 된다.
부모 패키지를 가리키기 위해 앞에 .
이 붙는다.
from . import echo
from .. import formats
from ..filters import equalizer
상대경로 import
의 경우 현재 모듈의 이름에 기반을 두기 때문에,(메인 모듈의 이름은 항상 __main__
임) 메인 모듈로 사용될 목적의 모듈들은 반드시 절대경로 import
를 사용해야한다. 그러니까 그냥 절대경로만 사용하자!