파이썬 튜터리얼 정리 6 모듈 モジュール (module)
대화형 인터프리터 (ex, 윈도우-명령 프롬프트)는 종료하면 만든 함수, 변수는 사라진다.
긴 프로젝트는 편집기(ex. atom)를 사용하여 (.py 파일)로 저장한다. -> '스크립트'
파이썬에서는 함수/변수/클래스가 들어있는 파일을 스크립트/인터프리터에서 불러서 사용할 수 있다
그런 파일을 '모듈'이라고 한다.
즉, 모듈이란
함수/변수/클래스들을 모아 놓은 파이썬 파일이다.
이미 만들어 놓은 모듈을 사용할 수도 있고, 직접 만들어서 사용할 수 도 있다.
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
>>> import fibo
>>> 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
from import
>>> from fibo import fib, fib2
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
from import *
>>> from fibo import *
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
import * : _로 시작하는 것을 제외한 모든 이름을 임포트 한다.
대부분 이 기능을 사용하지 않는데, 이미 정의한 것들을 가리게 할 수도 있기 때문.
하지만, 대화형 세션에서 입력을 줄이고자 사용하는 것은 상관없으나.. 잘 사용 x
import as
>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
from import as
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
if __name__ == "__main__":
mod1.py
def add(a, b):
return a+b
def sub(a, b):
return a-b
print(add(1, 4))
print(sub(4, 2))
위 파일을 import 하면,
C:\Users\pahkey> cd C:\doit
C:\doit> python
Type "help", "copyright", "credits" or "license" for more information.
>>> import mod1
5
2
mod1.py가 실행되어 5와 2가 출력된다!
이런 문제를 해결하기 위해 if __name__ == "__main__"
을 사용한다.
def add(a, b):
return a+b
def sub(a, b):
return a-b
if __name__ == "__main__":
print(add(1, 4))
print(sub(4, 2))
이 파일을 직접 실행하면 __name__ =="__main__"이 참이되어 if문 다음 문장들이 수행된다.
반대로 대화형 인터프리터나 다른 파일에서 이 모듈을 불러서 사용할 때는 거짓이 되어 수행하지 않는다.
위 같이 수정 후, 대화형 인터프리터를 열고 실행해 보자.
>>> import mod1
>>>
아무런 결과도 출력되지 않는다.
알아두기
파이썬의 __name__
변수는 파이썬이 내부적으로 사용하는 특별한 변수명이다. 만약 C:\doit>python mod1.py
처럼 직접 mod1.py 파일을 실행시킬 경우 mod1.py의 __name__
변수에는 __main__
이라는 값이 저장된다. 하지만 파이썬 쉘이나 다른 파이썬 모듈에서 mod1을 import 할 경우에는 mod1.py의 __name__
변수에는 "mod1"이라는 mod1.py의 모듈이름 값이 저장된다.
1.2. 모듈검색 경로
인터프리터에서 모듈이 임포트 될 때 검색 순서
내장 모듈 -> 변수 sys.path 디렉토리 리스트에서 파일 검색
sys.path 초기화
- 입력 스크립트를 포함하는 디렉토리 (파일이 지정되지 않았을 때, 현재 디렉토리)
- PYTHONPATH (디렉토리 이름들의 목록, 셸 변수 PATH와 같은 문법)
- 설치 의존적인 기본값
초기화 후, 파이썬 프로그램은 sys.path를 수정할 수 있습니다.
스크립트를 포함하는 디렉토리는 검색 경로의 처음 / 표준 라이브러리 경로의 앞에 놓임.
같은 이름일 경우 라이브러리 디렉토리에 있는 것 대신 스크립트를 포함하는 디렉토리의 것이 로드된다.
이 치환이 의도된 것이 아니라면 에러가 뜬다.
1.3. '컴파일'된 파이썬 파일 コンパイル" された Python ファイル
모듈 로딩을 빠르게 하기 위해,
__pycache__
디렉토리에 각 모듈의 컴파일된 버전을 module.version.pyc
파일이름으로 캐싱한다.
version은 컴파일된 파일의 형식을 지정한다. 일반적으로 파이썬의 버전 번호를 포함한다.
-> 서로 다른 버전과 파이썬의 배포에도 모듈이 공존할 수 있도록 함
ex) CPython 3.3 에서 배포 spam.py의 컴파일된 버전 :
__pycache__/spam.cpython-33.pyc
파이썬은 소스의 수정시간을 컴파일된 버전과 비교해서 다시 컴파일해야 하는지 검사합니다. - 완전히 자동화된 과정
컴파일된 모듈은 플랫폼 독립적 - 같은 라이브러리를 다른 아키텍처에서 공유할 수 있음.
캐시를 검사하지 않는 2가지 상황
1. 명령행에서 직접 로드되는 모듈
: 항상 재컴파일하고 결과를 저장하지 않음.
2. 소스 모듈이 없을 때
: 소스 없는 (컴파일된 파일만 있는) 배포를 지원하려면, 컴파일된 모듈이 소스 디렉토리에 있어야하고, 소스 모듈이 없어야 합니다.
전문가를 위한 몇 가지 팁
- 컴파일된 모듈의 크기를 줄이려면 파이썬 명령에
-O
나 -OO
스위치를 사용할 수 있습니다. -O
스위치는 assert 문을 제거하고, -OO
스위치는 assert 문과 __doc__ 문자열을 모두 제거합니다. 어떤 프로그램들은 이것들에 의존하기 때문에, 무엇을 하고 있는지 아는 경우만 이 옵션을 사용해야 합니다. "최적화된" 모듈은 opt-
태그를 갖고, 보통 더 작습니다. 미래의 배포에서는 최적화의 효과가 변경될 수 있습니다. .py
파일에서 읽을 때보다 .pyc
파일에서 읽을 때 프로그램이 더 빨리 실행되지는 않습니다; .pyc
파일에서 더 빨라지는 것은 로드되는 속도뿐입니다.- 모듈
compileall
은 디렉터리에 있는 모든 모듈의 .pyc 파일들을 만들 수 있습니다. - 이 절차에 대한 더 자세한 정보, 결정들의 순서도를 포함합니다, 는 PEP 3147 에 나옵니다.
6.2. 표준 모듈들 標準モジュール
파이썬은 표준 모듈을 지원 - 라이브러리 레퍼런스 참조
sys 모듈
: 모든 파이썬 인터프리터에 내장.
sys.ps1 / sys.ps2
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>
이 두개의 변수들은 대화형 모드일 때만 정의.
sys.path
변수 sys.path는 인터프리터의 모듈 검색 경로를 결정하는 문자열들의 '리스트'.
환경변수 PYTHONPATH에서 취한 기본 경로/ 설정되지 않았을 경우 내장 기본값으로 초기화.
표준 리스트 연산사용 가능
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')
6.3. dir()
함수
: 모듈이 정의하는 이름(문자열) '리스트' 리턴
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
'__package__', '__stderr__', '__stdin__', '__stdout__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
'_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
'call_tracing', 'callstats', 'copyright', 'displayhook',
'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
'thread_info', 'version', 'version_info', 'warnoptions']
인자 없으면, 현재 정의한 이름들을 나열
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
모든 형의 이름을 나열한다는 것에 유의. - 변수, 모듈, 함수 등등
내장 함수와 변수들의 이름은 나열 x - 원한다면 표준 모듈 builtins에 정의되어 있음.
>>> import builtins
>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
'__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
'zip']
6.4. 패키지 パッケージ
모듈 이름 A.B
는 A
라는 이름의 패키지에 있는 B
라는 이름의 서브 모듈
- 모듈사이 전역변수의 이름 중복을 걱정할 필요없게 함.
ex) 음향처리 모듈
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
...
- 파이선이 디렉토리를 패키지로 취급하려면 __init__.py
파일 필요
: String 처럼 흔히 쓰는 이름의 디렉토리가 검색을 방해하는 것을 방지하기 위해.
패키지-개별적 모듈 import
import sound.effects.echo
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
- 서브 모듈 import (from 패키지 import 모듈)
from sound.effects import echo
echo.echofilter(input, output, delay=0.7, atten=4)
- 함수, 변수 직접 import (from 패키지 import 아이템)
from sound.effects.echo import echofilter
echofilter(input, output, delay=0.7, atten=4)
* 찾지 못한다면 ImportError 발생
* import item.subitem.subsubitem
에서 마지막은 모듈/패키지는 가능 but 클래스/함수/변수 x
6.4.1. 패키지에서 * 임포트 하기 パッケージから * を import する
from sound.effects import *
: 패키지의 모든 모듈을 임포트하려 한다.
- 시간이 오래 걸림
- 명시적으로 임포트해야 실행되는 모듈도 실행되버림
-> 유일한 해결책 : 패키지 저자가 '패키지의 색인'을 명시적으로 제공한다.
: 패키지 > __init__.py
> __all__
제공
from package import *
를 만날 때 임포트 하는 모듈 목록제공
ex) sound/effects/__init__.py
__all__ = ["echo", "surround", "reverse"]
: from sound.effects import *
이 sound.effects
패키지의 세 서브 모듈들을 임포트하게 됨을 의미
- __all__
을 정의하지 않으면
from sound.effects import *
은 임포트 하지 않습니다;