모듈과 패키지(공학자를 위한 Python)
공학자를 위한 Python 책을 참고하여 작성하였습니다.
- 책 제목: 공학자를 위한 Python
- 지은이: 조정래
- url: https://wikidocs.net/book/1704
1. 모듈과 패키지
모듈(module)은 재사용할 목적으로 작성된 Python 소스 파일을 의미하며, import문으로 로딩하여 사용한다. 예를 들어 os 모듈은 os.py라는 파일로 작성되어 있으며 사용시에는 import os 등으로 로딩한다.
import os
os.getcwd()
'c:\\Users\\82104\\OneDrive\\바탕 화면\\study\\python\\book'
abs(), complex(), int(), list(), ord() 등의 내장함수(built-in function)를 제외한 모든 함수, 클래스들은 항상 모듈에 포함된다.
math 등의 일부 내장 모듈(built-in module)은 Python 언어 자체에 포함되어 있지만 나머지 모듈 / 패키지는 별도 파일 형태로 존재한다.
import sys
sys.builtin_module_names
('_abc',
'_ast',
'_bisect',
'_blake2',
'_codecs',
'_codecs_cn',
'_codecs_hk',
'_codecs_iso2022',
'_codecs_jp',
'_codecs_kr',
'_codecs_tw',
'_collections',
'_contextvars',
'_csv',
'_datetime',
'_functools',
'_heapq',
'_imp',
'_io',
'_json',
'_locale',
'_lsprof',
'_md5',
'_multibytecodec',
'_opcode',
'_operator',
'_pickle',
'_random',
'_sha1',
'_sha256',
'_sha3',
'_sha512',
'_signal',
'_sre',
'_stat',
'_statistics',
'_string',
'_struct',
'_symtable',
'_thread',
'_tracemalloc',
'_warnings',
'_weakref',
'_winapi',
'_xxsubinterpreters',
'array',
'atexit',
'audioop',
'binascii',
'builtins',
'cmath',
'errno',
'faulthandler',
'gc',
'itertools',
'marshal',
'math',
'mmap',
'msvcrt',
'nt',
'sys',
'time',
'winreg',
'xxsubtype',
'zlib')
패키지(package)는 모듈을 디렉토리 구조로 묶어놓은 것을 의미한다. 예를 들어 os는 os.py라는 파일로 존재하지만 대표적 수치 패키지인 NumPy는 numpy라는 폴더 내에 여러 모듈이 존재한다.
2. 모듈
2-1. 모듈 작성과 사용
모듈(module)은 단순히 재사용을 염두에 두고 작성한 Python 소스파일을 의미한다. 예를 들어 다음과 같이 mysolve.py라는 파일에 Newton 법과 bisection 법으로 방정식의 해를 구하는 함수를 작성했다고 가정하기로 한다.
# mysolver.py
tol = 1E-10
maxiter = 50
def solve_by_newton(func, der, x0):
""" solve equation by newton method """
x = x0
for i in range(maxiter):
f, df = func(x), der(x)
if abs(f) < tol:
return x
x = x-f/df
return None
def solve_by_bisection(func, lb, ub):
""" solve equation by bisection method """
for i in range(maxiter):
x = (lb + ub) / 2
if func(x) == 0 or (ub - lb) / 2 < tol:
return x
elif func(lb) * func(x) < 0:
ub = x
else:
lb = x
return None
# 모듈 사용
# import mysolver
def func(x):
return x * x - 2 * x - 4
def der(x):
return 2 * x - 2 # f(x), f'(x)
xNewton = solve_by_newton(func, der, 10) # 앞에 mysolver 붙여야 함.
xBisection = solve_by_bisection(func, 0, 10)
print('tol = ', tol)
print('x = ', xNewton, ', ', xBisection)
tol = 1e-10
x = 3.2360679774998244 , 3.2360679774865275
모듈을 사용하는 것은 확장자를 뺀 파일 이름으로 import module 형태로 로딩하여 사용하면 된다. 코드에서 확인할 수 있듯이 모듈 내의 함수, 변수, 클래스 등은 module.xxx 등과 같은 형태로 사용한다. 이 때 module은 namespace 역할을 한다.
2-2. 스크립트로 모듈 실행(모듈 테스트)
모듈은 기본적으로 import 문으로 스크립트나 다른 모듈에서 호출되어 사용되는 용도로 작성한다. 하지만 모듈을 작성 후 테스트를 수행하기 위해 스크립트로 실행될 수 있다. 이 경우 모듈 하단에 name__속성이 ‘__main‘인지 확인하여 실행시키는 것이 일반적인 방법이다. 다음은 Python 공식 튜토리얼에 소개된 fibo 모듈이다.
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print(b, end = ' ')
a, b = b, a + b
print()
if __name__ == '__main__':
import sys
fib(int(sys.argv[1]))
스크립트 실행
python fibo.py 100
1 1 2 3 5 8 13 21 34 55 89
인터프리터에서 사용하면 실행되지 않는다.
2-3. dir() 함수
내장함수 dir(module)은 모듈에서 정의하고 있는 변수, 함수 등을 출력해준다. 다음은 sys 모듈에 대해 임포트 후 dir(sys)를 적용한 예이다.
import sys
dir(sys)
['__breakpointhook__',
'__displayhook__',
'__doc__',
'__excepthook__',
'__interactivehook__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'__stderr__',
'__stdin__',
'__stdout__',
'__unraisablehook__',
'_base_executable',
'_clear_type_cache',
'_current_exceptions',
'_current_frames',
'_deactivate_opcache',
'_debugmallocstats',
'_enablelegacywindowsfsencoding',
'_framework',
'_getframe',
'_git',
'_home',
'_xoptions',
'addaudithook',
'api_version',
'argv',
'audit',
'base_exec_prefix',
'base_prefix',
'breakpointhook',
'builtin_module_names',
'byteorder',
'call_tracing',
'copyright',
'displayhook',
'dllhandle',
'dont_write_bytecode',
'exc_info',
'excepthook',
'exec_prefix',
'executable',
'exit',
'flags',
'float_info',
'float_repr_style',
'get_asyncgen_hooks',
'get_coroutine_origin_tracking_depth',
'get_int_max_str_digits',
'getallocatedblocks',
'getdefaultencoding',
'getfilesystemencodeerrors',
'getfilesystemencoding',
'getprofile',
'getrecursionlimit',
'getrefcount',
'getsizeof',
'getswitchinterval',
'gettrace',
'getwindowsversion',
'hash_info',
'hexversion',
'implementation',
'int_info',
'intern',
'is_finalizing',
'last_traceback',
'last_type',
'last_value',
'maxsize',
'maxunicode',
'meta_path',
'modules',
'orig_argv',
'path',
'path_hooks',
'path_importer_cache',
'platform',
'platlibdir',
'prefix',
'ps1',
'ps2',
'ps3',
'pycache_prefix',
'set_asyncgen_hooks',
'set_coroutine_origin_tracking_depth',
'set_int_max_str_digits',
'setprofile',
'setrecursionlimit',
'setswitchinterval',
'settrace',
'stderr',
'stdin',
'stdlib_module_names',
'stdout',
'thread_info',
'unraisablehook',
'version',
'version_info',
'warnoptions',
'winver']
3. 패키지
패키지(package)는 디렉토리 형태로 관련 모듈을 모아둔 것으로 이해할 수 있다. 보다 전문적으로 이야기하면 점(.)으로 모듈 이름을 활용할 수 있또록 구조화하는 방법을 의미한다. 다음은 Python 공식 튜토리얼에 소개된 설명을 정리한 것이다.
사운드 관련 패키지를 만든다고 가정하기로 한다. 이 경우 다음과 같은 파일 구조로 라이브러리를 구성한다.
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.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 할 수 있다 예를 들어 echo.py에 echofilter(…)라는 함수를 사용하려면 다음과 같다.
import sound.effects.echo
sound.effects.echo.echofilter(input, output, delay = 0.7, atten = 4)
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)
from sound.effects.echo import *
echofilter(input,output,delay=0.7,atten=4)
경우에 따라서 부 패키지(sub-package) 자체를 임포트할 수 있다. 즉, 원칙적으로 from module import * 형태 대신 from package import * 등과 같이 사용하려면 __init__.py에 __all__ 속성에 모듈명을 리스트 형태로 나열해야만 한다.
4. 라이브러리화된 모듈
4-1. 모듈 찾기 경로
한 프로젝트 내에서 사용되는 모듈은 같은 디렉토리 내에 존재하면 import로 로딩하여 사용하면 된다. 만약 라이브러리화해서 다른 프로젝트에도 사용하려면 Python에서 모듈을 찾는 경로를 이해해야 한다.
Python에서 import 문으로 주어진 모듈은 다음의 순서를 찾는다.
- 현재 작업 디렉토리(current working directory)
- Python 인스톨 디렉토리와 그 하위의 lib/site-packages 디렉토리 (Python 인터프리터마다 조금씩 다름)
- 환경변수 PYTHONPATH에 지정된 디렉토리
# working directory를 제외한 모듈 위치는 sys.path를 통해 접근
import sys
sys.path
['c:\\Users\\82104\\OneDrive\\바탕 화면\\study\\python\\book',
'c:\\Program Files\\Python310\\python310.zip',
'c:\\Program Files\\Python310\\DLLs',
'c:\\Program Files\\Python310\\lib',
'c:\\Program Files\\Python310',
'',
'C:\\Users\\82104\\AppData\\Roaming\\Python\\Python310\\site-packages',
'C:\\Users\\82104\\AppData\\Roaming\\Python\\Python310\\site-packages\\win32',
'C:\\Users\\82104\\AppData\\Roaming\\Python\\Python310\\site-packages\\win32\\lib',
'C:\\Users\\82104\\AppData\\Roaming\\Python\\Python310\\site-packages\\Pythonwin',
'c:\\Program Files\\Python310\\lib\\site-packages']
4-2. 자신만의 라이브러리화된 모듈 / 패키지
프로그램의 규모가 커지면 소스파일을 모듈로 분리하여 같은 디렉토리에 있도록 하여 실행한다. 만약 일부 모듈을 다른 프로그램에도 사용하려면 위에 설명한 바와 같이 모듈의 위치를 PYTHONPATH나 sys.path에 등록해야 한다.
# 환경변수 PYTHONPATH에 추가하는 방법: 항상 추가된다.
import myutils as utils
area = utils.compute_area([0, 0, 1, 0, 2, 1])
# sys.path에 추가하는 방법 : 현재 Python 프로세스에서만 유효하다.
import sys
sys.path.append(r'주소')
import myutils as utils
area = utils.compute_area([0, 0, 1, 0, 2, 1])
댓글남기기