패키지나 모듈을 파이썬이 찾을 수 있어야 import가 가능하다. 파이썬은 모듈과 패키지를 찾아야하고, 찾는 순서가 있다.
1번째 : sys.moudules
2번째 : built-in modules
3번째 : sys.path
파이썬이 모듈이나 패키지를 찾기위해 제일 먼저 확인한다. sys.modules는 사전형이다. 그리고 이미 import된 모듈과 패키지들을 저장하고 있다. 즉, 한번 import된 모듈과 패키지들은 파이썬이 또 다시 찾지 않아도 되는 기능을 가지고 있다. 그래서 새로 import하는 모듈은 sys.modules에서 찾을 수 없다.
파이썬에서 제공하는 파이썬 공식 라이브러리들 이다.
파이썬 인터프리터에는 많은 내장 함수가 있다. 인터프리터가 시작될 때 자동으로 로드되며 항상 사용이 가능하다. 내장 모듈은 C로 작성되며, 파이썬 인터프리터와 통합된다.
ex ) print(), input(), int(), float(), set() 등등..
파이썬이 마지막으로 찾는 sys.path이다. 모듈을 찾을 때 참조하는 경로를 나타낸다.
리스트 구조(string)이며, sys.path에 자기가 만든 모듈이 들어가있다면 모듈이 저장된 디렉터리로 이동할 필요 없이(내가 만든 모듈이나 패키지는 현재 디렉터리에 있는 것만 불러오기때문) 바로 불러서 사용할 수 있다. sys.path를 이용하여 모듈 검색 경로를 바꿔, 모듈들의 부르기 순서를 바꿀 수 있다. sys.path의 site-packages폴더에는 pip로 설치한 파이썬 패키지가 들어간다.
내가 만든 모듈이나 패키지 경로 지정 ex ) sys.path.append('내가 만든 모듈이 있는 디렉터리 경로')
sys.path에 정의되어 있는 디렉터리는 크게 3가지로 나뉜다.
sys.path 참고자료 : https://wikidocs.net/29
우선 sys모듈의 path변수는 모듈과 패키지의 검색 경로와 순서를 바꿀 수 있다. 내가 만든 모듈과 패키지의 검색 경로를 추가하여 사용할 수 있다.
sys모듈의 moudules변수에는 import한 모듈이 {모듈이름:모듈경로} 처럼 사전형으로 들어있다.
System-specific parameters and functions.
sys는 파이썬에서 제공하는 모듈이다. os모듈안에 있으며 파이썬 인터프리터가 제공하는 변수와 함수를 직접 제어할 수 있게 해주는 모듈이다. C언어로 작성되어 있다.
파이썬 공식문서 : https://docs.python.org/ko/3/library/sys.html?highlight=sys%20modules#sys.modules
영어만 보면 현기증이 나니까 영어 잘하는 분께 부탁해보자.
우선 sys.modules 를 출력해보자. 출력해보면 다음과 같이 나와있다.
'sys': <module 'sys' (built-in)>
sys 는 built-in modules 라는 것을 확인할 수 있다.
그렇다면 built-in이 된 모듈들은 어디서 찾아 볼 수 있을까?
sys.builtin_module_names 를 (내장모듈목록을튜플로반환함) 출력해보면 다음과 같이 나와있다.
('_abc', '_ast', '_codecs', '_collections', '_functools', '_imp', '_io', '_locale', '_operator', '_signal', '_sre', '_stat', '_string', '_symtable', '_thread', '_tracemalloc', '_warnings', '_weakref', 'atexit', 'builtins', 'errno', 'faulthandler', 'gc', 'itertools', 'marshal', 'posix', 'pwd', 'sys', 'time', 'xxsubtype')
이로써 sys는 인터프리터에 내장되있다는 것을 확인할 수 있다.
파이썬 스크립트로 넘어온 argument들의 리스트다.
import sys
print(sys.argv)
현재 발생한 예외정보를 튜플로 반환한다. (예외가 없는 경우 None을 리턴한다)
import sys
print(sys.exc_info())
파이썬이 설치된 경로와 실행파일을 나타낸다.
import sys
print(sys.prefix)
import sys
print(sys.exec_prefix)
import sys
print(sys.executable)
sys.executable은 파이썬 인터프리터의 실행파일 경로를 나타낸다
프로세스를 종료시킨다. (arg가 0인 경우에는 정상 종료도며, 0이 아닌 경우에는 비정상종료 처리)
파이썬 내장 모듈 목록을 반환한다.
객체의 참조 카운트 값을 반환한다. 일반적으로 이 값은 임시객체가 참조하는 경우도 포함되어서 1보다 크다.
import sys
num1 = 10
print(sys.getrefcount(num1)) #2를 반환..(임시객체가 참조하는 경우도 포함되서 1이 나와야하는데 2가나옴)
num2 = num1
print(sys.getrefcount(num2)) #3을 반환
현재 윈도우의 버전을 튜플로 반환한다.
import sys
print(sys.getwindowsversion())
설치된 파이썬의 저작권, 버전을 나타낸다.
현재 사용중인 기본 문자열 인코딩을 반환한다.
import sys
sys.getdefaultencoding() # utf-8 반환
표준 입력, 출력, 에러 스트림에 대응되는 파일 객체들을 나타낸다.
import sys
sys.stdout.write('hello world') # 표준 출력 스트림
sys.stderr.write('hi python') # 표준 에러 스트림
절대경로는 어떠한 경로를 알려줄때 절대적인 경로, 즉 고유 경로이다.
쉽게말해 우리집 주소를 쓸 때 대한민국 서울특별시 테헤란로 98길 32 처럼 모든 주소를 누구나 알 수 있게 정의하는 것이다. 프로그래밍상에선 절대경로를 알고있으면 현재 파일의 위치가 어디던 상관없이 그 경로로 접근이 가능하다. 절대경로는 최상위 디렉터리를 기준으로 한다.
디렉터리 구조가 이렇게 짜여있을때, main.py에서 my_module1.py의 func1 함수를 절대경로로 import 해보았다.
from py_package.my_module1 import func1
상대 경로는 쉽게말해 현재 내위치를(import하는 위치) 기준으로 경로를 작성하는 것이다.
쉽게 말해 우리집 주소를 상대 경로로 해석하면 절대경로와 같이 '대한민국 서울특별시 테헤란로 98길 32'가 되는 것이 아니라, '내가사는곳 98길 32'이 된다.
절대경로와는 다르게 항상 똑같은 경로를 기준으로 하는게 아니라 현재 파일의 위치를 기준으로 하기 때문에, local package안에서 다른 local package를 import할때 사용된다. 파일위치가 변경되면 경로 위치도 변경되어야 하는 단점이 있다. 그냥 편하게 절대경로를 쓰자.
practice 디렉터리 안에 main이라는 파이썬 파일과 pack1이라는 패키지가 존재하고,
pack1 패키지 안에 test1,test2,init 과 pack2 패키지가 존재하고,
pack2 패키지 안에 test3, init이 존재한다.
* pack1 -> __init__.py
절대경로 )
from pack1.test1 import *
from pack1.test2 import *
from pack1.pack2.test3 import *
__all__ = ['func1','func2','func3']
상대경로 )
from .test1 import *
from .test2 import *
from .pack2.test3 import *
__all__ = ['func1','func2','func3']
패키지 내부 init 파일에는 의존성이 있는 하위 패키지 까지 .(점)을 사용하여 상대경로로 접근도 가능하고 절대경로도 접근이 가능하다.
* main.py
절대경로 )
from pack1 import *
func1()
func3()
상대경로 )
from .pack1 import *
# err
func1()
func3()
사용하려는 패키지의 모든 모듈(*)을 import 하려니 절대경로로는 접근이 가능한데, 상대경로로는 접근이 불가능하다. error 을 내뱉는다.
ImportError: attempted relative import with no known parent package
이유는 python 자체에서 패키지와 모듈을 가져와 함수를 쓰는 곳에서는 상대경로로 접근자체가 불가능하게 막아놓았다.