내장 module인 math.py 에 정의 되어있는 factorial
함수를 사용하고자 합니다
import 과정이 어떻게 진행하는지 알아보겠습니다
import 과정의 깊은 내용(바이트코드 레벨) 링크
https://docs.python.org/3/tutorial/modules.html#the-module-search-path
>>> import math
>>> math.factorial(5)
120
import 후 module에 있는 내용에 접근 할때마다
"module을 매번 컴파일(complie) 해서 사용하는 걸까요?"
If the named module is not found in sys.modules, then Python’s import protocol is invoked to find and load the module. This protocol consists of two conceptual objects, finders and loaders. A finder’s job is to determine whether it can find the named module using whatever strategy it knows about. Objects that implement both of these interfaces are referred to as importers - they return themselves when they find that they can load the requested module.
Python includes a number of default finders and importers. The first one knows how to locate built-in modules, and the second knows how to locate frozen modules. A third default finder searches an import path for modules. The import path is a list of locations that may name file system paths or zip files. It can also be extended to search for any locatable resource, such as those identified by URLs.
The import machinery is extensible, so new finders can be added to extend the range and scope of module searching.
https://docs.python.org/3/reference/import.html#finders-and-loaders
Python Docs
Python의 import system의 과정(import 탐색 순서(Searching flow))를 도식화 해보면 다음과 같습니다
참고로 sys는 System-specific parameters and functions 의 약자 입니다
https://docs.python.org/3/library/sys.html#module-sys
>>> import sys
>>> sys.modules
{'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_io': <
module '_io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, 'time': <module 'time' (built-in)>, 'zipimport': <module 'zipimport' (frozen)>, '_codecs': <modul
e '_codecs' (built-in)>, 'codecs': <module 'codecs' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\codecs.py'>, 'encodings.aliases': <module 'encodings.aliases' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\encodings\\aliases.py'>, 'encodings': <module
'encodings' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\encodings\\__init__.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\encodings\\utf_8.py'>, '_codecs_kr': <module '_codecs_kr' (built-in)>, '_mu
ltibytecodec': <module '_multibytecodec' (built-in)>, 'encodings.cp949': <module 'encodings.cp949' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\encodings\\cp949.py'>, '_signal': <module '_signal' (built-in)>, '_abc': <module '_abc' (built-in)>, 'abc': <module 'abc' from 'C:\\Users\
\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\abc.py'>, 'io': <module 'io' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\io.py'>, '__main__': <module '__main__' (built-in)>, '_stat': <module '_stat' (built-in)>, 'stat': <module 'stat' from 'C:\\Users\\jigiseong\\AppD
ata\\Local\\Programs\\Python\\Python310\\lib\\stat.py'>, '_collections_abc': <module '_collections_abc' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\_collections_abc.py'>, 'genericpath': <module 'genericpath' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\
lib\\genericpath.py'>, 'ntpath': <module 'ntpath' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\ntpath.py'>, 'os.path': <module 'ntpath' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\ntpath.py'>, 'os': <module 'os' from 'C:\\Users\\jigiseong\\AppData\
\Local\\Programs\\Python\\Python310\\lib\\os.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\_sitebuiltins.py'>, 'itertools': <module 'itertools' (built-in)>, 'keyword': <module 'keyword' from 'C:\\Users\\jigiseong\\AppData\\Local\\Progra
ms\\Python\\Python310\\lib\\keyword.py'>, '_operator': <module '_operator' (built-in)>, 'operator': <module 'operator' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\operator.py'>, 'reprlib': <module 'reprlib' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\l
ib\\reprlib.py'>, '_collections': <module '_collections' (built-in)>, 'collections': <module 'collections' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\collections\\__init__.py'>, 'types': <module 'types' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\
\types.py'>, '_functools': <module '_functools' (built-in)>, 'functools': <module 'functools' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\functools.py'>, 'importlib._bootstrap': <module '_frozen_importlib' (frozen)>, 'importlib._bootstrap_external': <module '_frozen_importlib_exte
rnal' (frozen)>, 'warnings': <module 'warnings' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\warnings.py'>, 'importlib': <module 'importlib' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\importlib\\__init__.py'>, 'importlib.machinery': <module 'impor
tlib.machinery' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\importlib\\machinery.py'>, 'importlib._abc': <module 'importlib._abc' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\importlib\\_abc.py'>, 'collections.abc': <module 'collections.abc' from '
C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\collections\\abc.py'>, 'contextlib': <module 'contextlib' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\contextlib.py'>, 'enum': <module 'enum' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Pytho
n310\\lib\\enum.py'>, '_sre': <module '_sre' (built-in)>, 'sre_constants': <module 'sre_constants' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\sre_constants.py'>, 'sre_parse': <module 'sre_parse' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\sre_par
se.py'>, 'sre_compile': <module 'sre_compile' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\sre_compile.py'>, '_locale': <module '_locale' (built-in)>, 'copyreg': <module 'copyreg' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\copyreg.py'>, 're': <mod
ule 're' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\re.py'>, 'typing.io': <class 'typing.io'>, 'typing.re': <class 'typing.re'>, 'typing': <module 'typing' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\typing.py'>, 'importlib.abc': <module 'importl
ib.abc' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\importlib\\abc.py'>, 'importlib.util': <module 'importlib.util' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\importlib\\util.py'>, '_virtualenv': <module '_virtualenv' from 'C:\\Users\\jigiseong\\
PycharmProjects\\velog\\venv\\lib\\site-packages\\_virtualenv.py'>, 'site': <module 'site' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site.py'>, 'atexit': <module 'atexit' (built-in)>, 'math': <module 'math' (built-in)>}
>>> sys.path
['', 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip', 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\DLLs', 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib', 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310', 'C:\\Use
rs\\jigiseong\\PycharmProjects\\velog\\venv', 'C:\\Users\\jigiseong\\PycharmProjects\\velog\\venv\\lib\\site-packages']
sys.modules
sys.path
"The current working directory – denoted by an empty string – is handled slightly differently from other entries on sys.path."
https://docs.python.org/3/reference/import.html#path-entry-finders
Python Docs
list, dictionary 링크
공식 문서(Python Docs)에서 확인해보면
This mapping serves as a cache of all modules that have been previously imported, including the intermediate paths.
https://docs.python.org/3/reference/import.html#searching
"한 번 import 했던 module 은 sys.modules에 cache" 한다고 합니다.
"열심히 도식화 해봤는데 이해가 잘 가시나요? ㅎㅎ"
"정리해보자면"
import 하기위해 컴파일된 파일을 sys.modules 에 cache해 두었다가
다시 import 를 시도한다면 새로 컴파일 하는 것이 아니라
sys.modules 에 cache 해둔 컴파일한 파일에 접근합니다
import 후 module에 있는 내용에 접근 할때마다
"module을 매번 컴파일 해서 사용하는 걸까요?"
"당연하게도 아니였습니다!"
"자주 쓰이는 module의 컴파일 내용은 cache 처리와 dictionary의 특징을 살려 프로그램의 처리 속도를 올리고자 함이 팍팍 느껴지지 않나요 ㅎㅎ?"
의문점은 import math 후 import sys를 했는데 sys.modules에 'math' key가 생긴 것을 확인 할 수 있다.
아직 미해결
print() 와 같이 import 없이 사용 가능한 것은 어떤 logic 인걸까?
아직 미해결
math.py 와 마찬가지로 sys.py 도 내장 module 입니다
그런데 내장 module이 어떤 것이 있는지 궁금하지 않으신가요?
"sys는 System-specific parameters and functions 약자입니다. 따라서 system 자체가 갖다 쓸것 같은 변수명이 저장되어있을것 같다는 생각이 들지 않으셨나요? ㅎㅎ"
sys.py의 builtin_module_names 변수를 통해 확인할 수 있습니다
GUI 환경에서 확인해 보겠습니다
pycharm
따라서 명령어로 확인해 보겠습니다.
>>> 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')
---
사용 중인 interpreter의 내장 module들을 확인 할 수 있습니다.
물론 sys.modules나 sys.path 에 직접 경로를 Update 해도 import 가능합니다
project directory를 생성하면 해당 directory의 절대경로가 sys.path에 자동으로 추가됩니다.
project 위치와 site-packages 라는 정보가 저장됩니다.
따라서 import 시, import 탐색 순서 3번째에 단계에서 import에 성공하게 됩니다
내가 만든 local directory
velog 라는 project directory를 생성하였기에, sys.path에 자동으로 추가된 절대경로를 확인 할 수 있습니다
>>> sys.path
['', ... 중략 ...,
'C:\\Users\\jigiseong\\PycharmProjects\\velog\\venv', 'C:\\Users\\jigiseong\\PycharmProjects\\velog\\venv\\lib\\site-packages']
내장 module과 마찬가지로 local module 를 실행해보겠습니다
import sys
from calculator.add_and_multiply import add_and_multiply
if __name__ == '__main__':
print(add_and_multiply(1,2))
print(sys.modules)
또한 한 번의 import 후 sys.modules에 cache 되어있음을 확인 할 수 있습니다
C:\Users\jigiseong\PycharmProjects\velog\venv\Scripts\python.exe C:/Users/jigiseong/PycharmProjects/velog/main.py
5
{ ...중략..., '_virtualenv': <module '_virtualenv' from 'C:\\Users\\jigiseong\\PycharmProjects\\velog\\venv\\lib\\site-packages\\_virtualenv.py'>, 'site': <module 'site' from 'C:\\Users\\jigiseong\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site.py'>, 'calculator': <module 'calculator' from 'C:\\Users\\jigiseong\\PycharmProjects\\velog\\calculator\\__init__.py'>, 'calculator.multiplication': <module 'calculator.multiplication' from 'C:\\Users\\jigiseong\\PycharmProjects\\velog\\calculator\\multiplication.py'>, 'calculator.add_and_multiply': <module 'calculator.add_and_multiply' from 'C:\\Users\\jigiseong\\PycharmProjects\\velog\\calculator\\add_and_multiply.py'>}
Process finished with exit code 0