본문 바로가기

파이썬 튜터리얼 정리 6 모듈

파이썬 튜터리얼 정리 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 

# 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__"을 사용한다.

# mod1.py 
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 * 은 임포트 하지 않습니다;